home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
COMM
/
MSKRMSRC.ARJ
/
MSSSET.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-10-24
|
94KB
|
3,064 lines
NAME mssset
; File MSSSET.ASM
include mssdef.h
; Copyright (C) 1982,1991, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
; edit history:
; 6 Sept 1991 version 3.11
; Last edit 13 Aug 1991
public setcom, prmptr, dodef, setcpt, docom, stkadr, rdbuf
public setrx, rxtable, srvdsa, srvena, mcctab, takopen, takclos, ask
public askq, assign, initibm, mccptr, setinpbuf, setrollb, npages
public xfchtab, xftyptab, com1port, com2port, com3port, com4port,
public flotab, popcmd, domacptr, warntab, portirq, dodecom
public tcpdata, tcphost
braceop equ 7bh ; opening curly brace
bracecl equ 7dh ; closing curly brace
maketab MACRO ; Assembler Macro to make rxtable [jrd]
cnt = 0
rept 256
db cnt ; initialize table to 0 .. 255
cnt = cnt + 1
endm
db 0 ; table off (0) or on (1) indicator
ENDM
data segment
extrn comand:byte, flags:byte, trans:byte, takadr:word, taklev:byte
extrn portval:word, dtrans:byte, spause:byte, machnam:byte
extrn filtst:byte, maxtry:byte, script:byte, denyflg:word
extrn sloghnd:word, ploghnd:word, tloghnd:word
extrn decbuf:byte, kstatus:word, errlev:byte, srvtmo:byte
extrn luser:byte, lpass:byte, partab:byte, destab:byte, blktab:byte
extrn seoftab:byte, dmpname:byte, lsesnam:byte, lpktnam:byte
extrn ltranam:byte, incstb:byte, inactb:byte, rxoffmsg:byte
extrn rxonmsg:byte, scpbuflen:word, oldtak:byte, setchtab:byte
extrn prnname:byte, prnhand:word
rxtable equ THIS BYTE ; build 256 byte Translation Input table
maketab ; table rxtable is used by Connect mode
kerm db 'MS-Kermit>',0 ; default asciiz prompt
prm db 60 dup (0) ; buffer for new prompt
rdbuf db cmdblen dup (?) ; work space; room for macro def
; and for Status display line
stflg db 0 ; Says if setting SEND or RECEIVE parameter
defkind db 0 ; 0 for ASSIGN, 1 for DEFINE
ermes1 db cr,lf,'?Too many macro names$'
ermes2 db cr,lf,bell,'?No room for Take file buffer or Macro definition'
db cr,lf,bell,'$'
ermes4 db cr,lf,'?Too many active Take files and Macros',cr,lf, bell,'$'
ermes5 db cr,lf,'?Not implemented$'
ermes6 db cr,lf,'?More parameters are needed$'
ermes7 db cr,lf,'?Cannot use RTS/CTS on non-UART ports$'
errcap db cr,lf,'?Unable to open that file$'
erropn db cr,lf,'?Log file is already open$'
askhlp1 db 'Variable name then prompt string$'
askhlp2 db 'Prompt string$'
askhlp3 db 'Enter a line of text$'
filhlp db ' Output filename for the log$'
dishlp db cr,lf,' Quiet (no screen writing), Regular (normal),'
db ' Serial (non-formatted screen)'
db cr,lf,' and/or 7-BIT (default) or 8-BIT wide characters.$'
remhlp db cr,lf,' OFF to show file transfer display,'
db ' ON for quiet screen$'
macmsg db ' Specify macro name followed by body of macro, on same line$'
prmmsg db cr,lf
db ' Enter new prompt string or nothing to regain regular prompt.'
db cr,lf,' Use \123 notation for special chars (Escape is \27)$'
srxhlp1 db cr,lf,' Enter code for received byte code for'
db ' local byte ',cr,lf,' use ascii characters themselves or'
db cr,lf,' numerical equivalents of \nnn decimal'
db ' or \Onnn octal or \Xnnn hexadecimal',cr,lf
db ' or keywords ON or OFF (translation is initially off)'
db cr,lf,'$'
badrx db cr,lf,'?Expected ON, OFF, or \nnn$'
takchlp db cr,lf,'Value 0 to 65535 for COUNT in script IF COUNT command$'
takcerr db cr,lf,'?Note: command is valid only in Take files and Macros$'
dmpdefnam db 'Kermit.scn',0 ; asciiz default screen dump filename
prndefnam db 'PRN',0 ; asciiz default printer name
nummsg1 db cr,lf,'?Use a number between $'
nummsg2 db ' and $'
srvthlp db 'seconds, 0-255, waiting for a transaction$'
unkchhlp db cr,lf,' Disposition of files arriving with unknown'
db ' character sets:',cr,lf,' Keep (default), Cancel$'
winhelp db cr,lf,'Number of sliding window slots 1 (no windowing) to 31.'
db cr,lf,'This also subdivides the 2000 byte main packet buffer'
db cr,lf,'and may reduce the Send and Receive packet lengths.$'
ctlhlp db ' Decimal number between 0 and 31$'
dmphlp db ' Filename to hold screen dumps$'
prnhlp db ' Filename for printer output (default is PRN)$'
prnerr db cr,lf,' Cannot open that name. Using default of PRN$'
erlhlp db ' Decimal number between 0 and 255$'
pakerr db cr,lf,'?Choose a decimal number '
db 'from 20 to 94 (normal) or to 2000 (long)$'
pakhlp db cr,lf,'Decimal number between 20 and 94 (normal) or '
db '2000 (long)$'
padhlp db cr,lf,' Decimal number between 0 and 31 or 127$'
pauhlp db ' Decimal number between 0 and 127$'
quohlp db ' Decimal number between 33 and 126$'
retryhlp db ' Decimal number between 1 and 63$'
dblhlp db ' Decimal number between 0 and 255$'
luserh db cr,lf,'Username Password from remote Kermit (0-16 chars each)$'
lpassh db cr,lf,'Password from remote Kermit (0-16 chars,'
db ' spaces allowed)$'
timhlp db ' Decimal number between 0 and 94$'
delyhlp db ' Delay seconds before sending file (0-63)$'
eschlp db cr,lf,'Press literal control keys (ex: Control ]) or'
db ' enter in \nnn numerical form$'
escerr db cr,lf,'?Not a control code$'
hnd1hlp db cr,lf,'XON (\17), XOFF (\19), CR (\13), LF (\10), BELL (\7),'
DB ' ESC (\27), NONE (\0)'
db cr,lf,' or "CODE" followed by decimal number$'
intoms db 'number of seconds to wait before timeout',cr,lf,'$'
loghlp db cr,lf
db ' PACKETS - during file transfers (to default file PACKET.LOG)'
db cr,lf
db ' SESSION - during Connect mode (to default file SESSION.LOG)'
db cr,lf
db ' TRANSACTIONS - files transfers (to default file TRANSACT.LOG)'
db cr,lf,' followed by an optional filename for the log.$'
comhlp db cr,lf,' Address of the COM1 - COM4 port (ex: COM3 \x02f8 or'
db ' COM4 \x02e8)$'
irqhlp db cr,lf,' Enter, or IRQ of port (ex: \3)$'
debhlp db cr,lf,' PACKETS - during file transfers' ; Debugging
db cr,lf,' SESSION - during Connect mode'
db cr,lf,' ON - both packets and session'
db cr,lf,' OFF - turns off all debugging$'
dohlp db cr,lf,'definitions of variables (\%n), or press ENTER key$'
sdshlp db cr,lf,'DISABLE or ENABLE access to selected Server commands:'
db cr,lf
db ' CD/CWD, DEL, DIR, FINISH (includes BYE & LOGOUT), GET,'
db ' HOST, KERMIT, LOGIN,',cr,lf
db ' PRINT, SEND, SPACE, TYPE, and ALL.$'
xfchhlp db cr,lf,' Which character set to put on the wire during file'
db ' transfers:',cr,lf
db ' TRANSPARENT (regular PC codes)',cr,lf
db ' LATIN1 (ISO 8859-1)',cr,lf
db ' CYRILLIC (ISO 8859-5)$'
xfchbad db cr,lf,'Warning: forcing SET FILE CHARACTER-SET of CP866$'
setchmsg db cr,lf,'Warning: forcing SET TRANSFER CHARACTER-SET of CYRILLIC$'
xfilhlp db 'NONE, SPACE, or filler character$'
xpmthlp db 'Host echo char acting as prompt, \1-\255$'
pophlp db 'Status value to be returned, nothing if no new value$'
crlf db cr,lf,'$'
srvtab db 2 ; SET SERVER table
mkeyw 'Login',1
mkeyw 'Timeout',2
sethlp db cr,lf
db ' Alarm sec from now or HH:MM:SS '
db ' Log kind opt filename'
db cr,lf
db ' Attributes packets on/off '
db ' Mode-line on/off'
db cr,lf
db ' Bell on/off at end of xfers '
db ' NetBios-name (our local name)'
db cr,lf
db ' Block-check-type checksum/CRC '
db ' Parity even/odd/mark/space/none'
db cr,lf
db ' COM1 - COM4 address '
db ' Port for i/o 1/2/COM1/COM2/etc'
db cr,lf
db ' COUNT number a loop counter '
db ' Printer filespec for Connect mode'
db cr,lf
db ' Debug on/off display packets '
db ' Prompt string (new Kermit prompt)'
db cr,lf
db ' Default-disk '
db ' Receive parameter many things'
db cr,lf
db ' Delay secs before Sending file '
db ' Remote on/off show xfer counts?'
db cr,lf
db ' Destination Disk/Screen/Printer '
db ' Retry limit for packet send/receive'
db cr,lf
db ' Display quiet/reg/serial show cnts?'
db ' Send parameter many things'
db cr,lf
db ' Dump filespec screen to disk '
db ' Server parameter'
db cr,lf
db ' Duplex half or full '
db ' Speed or Baud many speeds'
db cr,lf
db ' EOF Ctrl-Z/NoCtrl-Z ^Z ends file? '
db ' Take-echo on/off display commands?'
db cr,lf
db ' End-of-line char cr or whatever '
db ' Terminal none/H-19/VT52/VT102/VT320'
db cr,lf
db ' Errorlevel number for DOS Batch '
db ' and many terminal setup parameters'
db cr,lf
db ' Escape char ^] or whatever '
db ' TCP/IP address,mask,nameserver etc'
db cr,lf
db ' File (Character-set, Type, Warning)'
db ' Timer on/off time packet waiting'
db cr,lf
db ' Flow-control NONE XON/XOFF RTS/CTS'
db ' Translation IN Connect mode rcv''d char'
db cr,lf
db ' Handshake xon/xoff/cr/lf/bell/esc..'
db ' Transfer Character-set (on wire) '
db cr,lf
db ' Incomplete file keep/discard '
db ' Transmit parameters, for scripts'
db cr,lf
db ' Input timeout, etc (for scripts) '
db ' Unknown-character-set (keep/cancel)'
db cr,lf
db ' Key key-ident definition '
db ' Warning on/off if file renamed'
db cr,lf
db ' Local-echo on/off '
db ' Windows number of sliding window slots'
db '$'
settab db 51 ; Set table
mkeyw 'Alarm',setalrm
mkeyw 'Attributes',setatt
mkeyw 'Baud',baudst
mkeyw 'Bell',bellst
mkeyw 'Block-check-type',blkset
mkeyw 'COM1',com1port
mkeyw 'COM2',com2port
mkeyw 'COM3',com3port
mkeyw 'COM4',com4port
mkeyw 'Count',takectr
mkeyw 'Debug',debst
mkeyw 'Default-disk',cwdir
mkeyw 'Delay',setdely
mkeyw 'Destination',desset
mkeyw 'Display',disply
mkeyw 'Dump',setdmp
mkeyw 'Duplex',setdup
mkeyw 'End-of-Line',eolset
mkeyw 'EOF',seteof
mkeyw 'Errorlevel',seterl
mkeyw 'Escape',escset
mkeyw 'File',setfile
mkeyw 'Flow-control',floset
mkeyw 'Handshake',hndset
mkeyw 'Incomplete',abfset
mkeyw 'Input',inpset
mkeyw 'Key',setkey
mkeyw 'Local-echo',lcal
mkeyw 'Log',setcpt ; same as log command
mkeyw 'Mode-line',modl
mkeyw 'NetBios-name',setnbios
mkeyw 'Parity',setpar
mkeyw 'Port',coms
mkeyw 'Printer',setprn
mkeyw 'Prompt',promset
mkeyw 'Receive',recset
mkeyw 'Remote',remset
mkeyw 'Retry',retryset
mkeyw 'Send',sendset
mkeyw 'Server',setsrv
mkeyw 'Speed',baudst
mkeyw 'Take-echo',takset
mkeyw 'TCP/IP',tcpipset
mkeyw 'Terminal',vts
mkeyw 'Timer',timset
mkeyw 'Transfer',sxfer
mkeyw 'Translation',setrx
mkeyw 'Transmit',setxmit
mkeyw 'Unknown-character-set',unkchset
mkeyw 'Warning',filwar
mkeyw 'Windows',winset
setfitab db 5 ; Set File command table
mkeyw 'Character-Set',1
mkeyw 'Collision',0
mkeyw 'Display',3
mkeyw 'Type',2
mkeyw 'Warning (Collision)',0
xfertab db 1 ; SET TRANSFER table
mkeyw 'Character-set',0
xfchtab db 3 ; SET TRANSFER CHARACTER-SET
mkeyw 'TRANSPARENT',0 ; no translation
mkeyw 'Latin1 ISO 8859-1',1 ; ISO 8859-1, Latin-1
mkeyw 'Cyrillic ISO 8859-5',2 ; ISO 8859-5/Cyrillic, CP866
xftyptab db 2 ; SET FILE TYPE table
mkeyw 'Binary',1 ; Binary = as-is
mkeyw 'Text',0 ; Text = can change char sets
warntab db 6 ; File Warning table
mkeyw 'Overwrite',1 ; overwrite
mkeyw 'Rename',0 ; rename
mkeyw 'Discard',4 ; discard
mkeyw 'No-supersede',4 ; discard
mkeyw 'on (rename)',0 ; old form
mkeyw 'off (overwrite)',1 ; old form
unkctab db 2 ; unknown character-set disposition
mkeyw 'Keep',0
mkeyw 'Cancel',1
atttab db 6 ; SET ATTRIBUTES table
mkeyw 'Off',00ffh ; all off
mkeyw 'On',10ffh ; all on (high byte is on/off)
mkeyw 'Character-set',attchr ; Character set
mkeyw 'Date-Time',attdate ; Date and Time
mkeyw 'Length',attlen ; Length
mkeyw 'Type',atttype ; Type
comtab db 2 ; table of COM ports
mkeyw 'COM3',4 ; offset of COM3 address
mkeyw 'COM4',6 ; offset of COM4 address
stsrtb db 10 ; Number of options
mkeyw 'Packet-length',srpack
mkeyw 'Padchar',srpad
mkeyw 'Padding',srnpd
mkeyw 'Pause',srpaus
mkeyw 'Start-of-packet',srsoh
mkeyw 'Quote',srquo
mkeyw 'End-of-packet',sreol
mkeyw 'Timeout',srtim
mkeyw 'Double-char',srdbl
mkeyw 'Ignore-char',srign
ontab db 2
mkeyw 'off',0
mkeyw 'on',1
distab db 5 ; Set Display mode
mkeyw '7-bit',7 ; controls bit d8bit in flags.remflg
mkeyw '8-bit',8 ; sets d8bit
mkeyw 'Quiet',dquiet ; values defined in header file
mkeyw 'Regular',dregular
mkeyw 'Serial',dserial
distab2 db 3 ; for SET FILE DISPLAY
mkeyw 'Quiet',dquiet ; values defined in header file
mkeyw 'Regular',dregular
mkeyw 'Serial',dserial
; If abort when receiving files, can keep what we have or discard
abftab db 2
mkeyw 'Discard',1
mkeyw 'Keep',0
flotab db 3
mkeyw 'none',0
mkeyw 'xon/xoff',1
mkeyw 'RTS/CTS',2
hndtab db 8
mkeyw 'none',0
mkeyw 'bell',bell
mkeyw 'cr',cr
mkeyw 'esc',escape
mkeyw 'lf',lf
mkeyw 'xoff',xoff
mkeyw 'xon',xon
mkeyw 'code',0ffh ; allow general numerial code
duptab db 2 ; SET DUPLEX table
mkeyw 'full',0
mkeyw 'half',1
inptab db 4 ; Scripts. Set Input
mkeyw 'Case',inpcas ;[jrs]
mkeyw 'Default-timeout',inptmo ;[jrs]
mkeyw 'Echo',inpeco ;[jrs]
mkeyw 'Timeout-action',inpact ;[jrs]
xmitab db 3 ; SET TRANSMIT table
mkeyw 'Fill-empty-line',0
mkeyw 'Line-Feeds-sent',1
mkeyw 'Prompt',2
debtab db 4 ; Set Debug command
mkeyw 'Off',0
mkeyw 'On',logpkt+logses
mkeyw 'Packets',logpkt
mkeyw 'Session',logses
logtab db 3 ; LOG command
mkeyw 'Packets',logpkt
mkeyw 'Session',logses
mkeyw 'Transactions',logtrn
srvdetab db 14 ; Server Enable/Disable list
mkeyw 'All',0fffh
mkeyw 'CD',cwdflg
mkeyw 'CWD',cwdflg
mkeyw 'Delete',delflg
mkeyw 'Dir',dirflg
mkeyw 'Finish',finflg
mkeyw 'Get',getsflg
mkeyw 'Host',hostflg
mkeyw 'Kermit',kerflg
mkeyw 'Login',pasflg
mkeyw 'Print',prtflg
mkeyw 'Send',sndflg
mkeyw 'Space',spcflg
mkeyw 'Type',typflg
trnstab db 2 ; Set Translation table
mkeyw 'Input',1
mkeyw 'Keyboard',2
tcptable db 8 ; TCP/IP command
mkeyw 'address',1 ; local Internet address
mkeyw 'domain',2 ; local domain string
mkeyw 'broadcast',8 ; broadcast of all 0's or all 1's
mkeyw 'gateway',4 ; gateway address
mkeyw 'primary-nameserver',5 ; address
mkeyw 'secondary-nameserver',6
mkeyw 'subnetmask',3 ; our subnet mask
mkeyw 'host',7 ; host's IP name or IP number
hosthlp db cr,lf,'Internet name or number (ddd.ddd.ddd.ddd) of '
db 'the remote machine$'
domainhlp db cr,lf,'Name of your domain$'
subnethlp db cr,lf,'Subnetmask, decimal ddd.ddd.ddd.ddd$'
addrhelp db cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd, of this'
db ' machine or BOOTP or RARP$'
iphelp db cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd$'
domainbad db cr,lf,'?Bad domain name, use is such as my.domain.name$'
addressbad db cr,lf,'?Bad Internet address, string is too long$'
hostbad db cr,lf,'?Bad host, use IP name or IP number$'
tcpaddress db 'unknown',(32-($-tcpaddress)) dup (0),0
tcpsubnet db '255.255.255.0',(32-($-tcpsubnet)) dup (0),0
tcpdomain db 'unknown',(32-($-tcpdomain)) dup (0),0
tcpgateway db 'unknown',(32-($-tcpgateway)) dup (0),0
tcpprimens db 'unknown',(32-($-tcpprimens)) dup (0),0
tcpsecondns db 'unknown',(32-($-tcpsecondns)) dup (0),0
tcphost db (32 -($-tcphost)) dup (0),0
tcpbcast db '255.255.255.255',(32-($-tcpbcast)) dup (0),0
tcpdata dw offset tcpaddress ; externally visible far pointers
dw offset tcpsubnet
dw offset tcpdomain
dw offset tcpgateway
dw offset tcpprimens
dw offset tcpsecondns
dw offset tcphost
dw offset tcpbcast
; MACRO DATA STRUCTURES mcctab
mcclen equ macmax*10 ; length of mcctab
mcctab db 0 ; macro name table entries
db mcclen dup (0) ; room for macro structures
; END OF MACRO DATA STRUCTURES
ibmmac db 'IBM ' ; startup IBM macro definition + space
db 'set timer on,set parity mark,set local-echo on,'
db 'set handshake xon,set flow none,',0 ; asciiz
even
prmptr dw kerm ; pointer to prompt
tempptr dw 0 ; pointer into work buffer
domacptr dw 0 ; pointer to DO MAC string
min dw 0
max dw 0
numerr dw 0
numhlp dw 0
temp dw 0
temp1 dw 0 ; Temporary storage
temp2 dw 0 ; Temporary storage
askecho db 0 ; ask's echo control flag
temptc db 3,0,0,'T',0,0 ; temp, for takclos, word cnt,<null>T#
deftemp dw 0
stkadr dw 0 ; non-zero if replacement keyboard xlator present
mccptr dw mcctab ; ptr to first free byte in mcctab
macptr dw 0 ; temp to hold segment of string
npages dw 10 ; # of pages of scrolling on each side
portirq db 4 dup (0) ; user specified IRQ's for COM1..4
data ends
code1 segment
extrn makebuf:far
code1 ends
code segment
extrn comnd:near, baudst:near, prompt:near, coms:near, cwdir:near
extrn isfile:near, strlen:near, strcpy:near, cnvlin:near
extrn katoi:near, decout:near, vts:near, setalrm:near, serrst:near
extrn prnopen:near, pntflsh:near
extrn setnbios:near ; in MSXIBM, needs stub for other machines
assume cs:code, ds:data, es:nothing
; DO defined macro command
; DO macname variable variable also defines variables \%1, \%2, ...\%9
DOCOM PROC NEAR
mov dx,offset mcctab ; table of macro defs
xor bx,bx ; help is table
mov ah,cmkey ; get key word (macro name)
call comnd ; get pointer to keyword structure
jnc docom1 ; nc = success, bx = 16 bit data
ret ; failure
docom1: mov domacptr,bx ; segment of definition string
mov comand.cmquiet,0 ; permit command echoing
mov bx,offset decbuf ; point to borrowed work buffer
mov word ptr[bx],0 ; clear buffer
mov dx,offset dohlp ; help
mov comand.cmblen,length rdbuf ; length of analysis buffer
mov ah,cmline ; get line of text, if any
call comnd
jnc docom2 ; nc = success
ret ; failure
docom2: mov deftemp,ax ; save byte count of command args
call hidemac ; hide previous \%0..\%9 macros
call getname ; get name of this macro
mov cx,word ptr rdbuf ; length of "\%0 plus found name"
call dodecom ; add keyword+def using DEF MAC below
jnc docom2a ; nc = success
ret
docom2a:call docnv ; convert macro string
jnc docom2b ; nc = success
ret
docom2b:mov max,1 ; temp for counting 1 + number args
mov word ptr rdbuf+4,' 1' ; number of first variable
docom3: mov word ptr rdbuf,0 ; clear length field, install \%x name
mov word ptr rdbuf+2,'%\' ; start with '\%1 '
mov word ptr rdbuf+6,0 ; clear text field
mov tempptr,offset rdbuf+6 ; pointer to location of found word
xor ch,ch ; make cx = 1 - 9
mov cl,rdbuf+4 ; cx = word # of interest, for getwrd
sub cl,'0' ; remove ascii bias
mov si,offset decbuf ; source = work buffer (borrowed)
call getwrd ; get CX-th word from work buf (1-9)
cmp deftemp,0 ; length of word, was it found?
je docom4 ; e = no, end variable definition part
add deftemp,4 ; count '\%n ' in command line length
inc max ; one more argument
mov cx,deftemp ; command length for dodecom
call dodecom ; add keyword+def using DEF MAC below
jnc docom3a
ret ; failure
docom3a:inc rdbuf+4 ; inc number of variable in '\%n '
cmp rdbuf+4,'9'
jbe docom3 ; do '1' through '9', if available
; DO the macro itself
docom4: cmp taklev,maxtak ; room in take level?
jl docom5 ; l = yes, continue
mov dx,offset ermes4 ; else complain
jmp reterr
docom5: inc taklev ; increment take level
add takadr,size takinfo ; create a Take macro
mov bx,takadr ; point to current structure
push es
mov es,domacptr ; segment of macro definition string
mov [bx].takbuf,es ; remember in Take structure
mov cx,es:word ptr [0] ; length of definition string
pop es
mov [bx].takcnt,cx ; # of chars in buffer
mov [bx].taktyp,0ffh ; flag as a macro
mov [bx].takptr,2 ; point to beginning of def text
mov cx,max ; 1 + number of arguments
mov [bx].takargc,cx
clc ; success
ret
DOCOM ENDP
; Create a new macro, named <0>T<taklev digit>, with the command line of the
; original macro modified to replace bare commas with Carriage Returns.
; Enter with domacptr pointing at the segment of the macro's definition.
; Return with domacptr pointing at the new buffer created by dodecom.
docnv proc near
cmp taklev,maxtak ; room in take level?
jb docnv1 ; b = yes
mov dx,offset ermes4 ; say too many Take files
mov ah,prstr ; display error message
int dos
stc ; set carry for failure
ret
docnv1: push es
mov word ptr rdbuf,3 ; length of name, 3 bytes <null>Tn
mov rdbuf+2,0
mov rdbuf+3,'T' ; name of <null>Tn
mov al,taklev ; Take level digit
inc al ; for what will be next Take level
add al,'0' ; add ascii bias
mov rdbuf+4,al ; last of the name
mov rdbuf+5,' ' ; separate dummy definition
mov ax,domacptr
mov es,ax ; seg of definition
xor si,si ; offset of definition
mov di,offset rdbuf+6 ; destination
mov cx,es:[si] ; read count of string
add si,2 ; point at string itself
xor bl,bl ; brace count
mov dl,braceop ; opening brace (we count them up)
mov dh,bracecl ; closing brace (we count them down)
xor bp,bp ; offset of last closing brace+1
cmp es:[si],dl ; starts with opening brace?
jne docnv2 ; ne = no
inc si ; skip this new leading space
dec cx ; and don't count it either
inc bh ; say opening brace was found
docnv2: mov al,es:[si] ; read a char
inc si
cmp al,dl ; opening brace?
jne docnv3 ; ne = no
inc bl ; count brace level
jmp short docnv5
docnv3: cmp al,dh ; closing brace?
jne docnv4 ; ne = no
dec bl
or bl,bl ; below 0?
jg docnv4 ; g = no, still in braces
jz docnv5 ; matching interior braces
or bh,bh ; was there an opening brace?
jz docnv5 ; z = no, record this one
xor bx,bx ; found opening match, reset to zero
jmp short docnv6 ; omit the brace
docnv4: or bl,bl ; in braced clause?
jnz docnv5 ; nz = yes, treat comma as literal
cmp al,',' ; unbraced comma?
jne docnv5 ; ne = no
mov al,CR ; replace bare comma with CR
docnv5: mov [di],al
inc di
docnv6: loop docnv2
pop es
cmp byte ptr [di-1],cr ; ends on a Carriage Return?
je docnv7 ; e = yes
mov byte ptr [di],cr ; insert one to do sync execution
inc di
docnv7: mov byte ptr [di],0 ; null terminator, for safety
sub di,offset rdbuf+2 ; start of string (skips count)
mov cx,di ; length of string
call dodecom ; define macro from rdbuf+2
mov domacptr,ax ; seg of new string
ret
docnv endp
; Extract CX-th word (cx = 1-9) from buffer (DI). Enter with si = source
; string and tempptr pointing at destination. Returns deftemp (count) of
; transferred characters. Allow string in curly braces to exist as a word.
; Adjacent curly braced strings are separate "words":
; {this is word-one}{this is word-two}word-three.
; First level curly braces are removed.
; All registers preserved.
getwrd proc near
push si
push di
push es
push ds
pop es ; set es to data segment
getwr1: push cx ; save word counter (1-9)
mov deftemp,0 ; no bytes transferred yet
mov di,tempptr ; where to store word/string
mov byte ptr [di],0 ; clear destination
mov dx,si ; start looking here in work buf
call strlen ; cx = remaining length of work buf
jcxz getwr6 ; z = nothing there, quit
getwr2: lodsb
cmp al,' ' ; skip leading whitespace
loope getwr2
dec si ; return to break char
; Parse curly brace delimited string
; end with si after closing brace
xor dl,dl ; assume "opening brace" is a null
mov dh,' ' ; assume "closing brace" is a space
mov cx,1 ; we are at brace level 1
cmp byte ptr [si],braceop ; starting with a real opening brace?
jne getwr3 ; ne = no
inc si ; skip opening brace
dec cx
mov dl,braceop ; opening brace (we count them up)
mov dh,bracecl ; closing brace (we count them down)
getwr3: cld ; search forward
lodsb ; read a char
stosb ; store in output buffer
or al,al ; at end of text?
jnz getwr3a ; nz = no
dec si ; stay at null terminator
dec di
jmp short getwr6 ; we are done with this "word"
getwr3a:inc deftemp ; count copied char
cmp al,dl ; an opening brace?
jne getwr4 ; ne = no
inc cx ; yes, increment brace level
jmp short getwr3 ; and continue scanning
getwr4: cmp al,dh ; closing brace?
jne getwr3 ; ne = no, continue scanning
dec cx ; yes, decrement brace level
cmp byte ptr [si],0 ; have we just read the last char?
jne getwr5 ; no, continue scanning
xor cx,cx ; yes, this is the closing brace
getwr5: or cx,cx ; at level 0?
jg getwr3 ; g = no, #opening <> #closing braces
dec di ; don't write closing brace
dec deftemp ; do not count closing brace
getwr6: pop cx ; recover word counter
mov byte ptr [di],0
jcxz getwrx ; just in case
loop getwr1 ; do until desired word is copied
getwrx: pop es
pop di
pop si
ret
getwrd endp
; Get macro name, given the action pointer in domacptr.
; Return rdbuf as word:length that follows, then "\%0 macro-name"
getname proc near
push bx
push cx
push dx
push si
push di
mov dx,domacptr ; action word to be matched
mov bx,offset mcctab+1 ; table of macro names, skip count
mov word ptr rdbuf,4 ; name length and space
mov word ptr rdbuf+2,'%\' ; define '\%0 '
mov word ptr rdbuf+4,' 0'
mov cl,mcctab ; number of entries
xor ch,ch
jcxz getnam3 ; z = empty table
getnam1:push cx
mov cx,[bx] ; length of name
mov si,bx ; point at structure member
add si,2 ; plus count
add si,cx ; plus length of name
mov ax,[si] ; get action word
cmp ax,dx ; correct action word?
jne getnam2 ; ne = no
push es
push ds
pop es
add word ptr rdbuf,cx ; length of macro \%0 + name
mov di,offset rdbuf+6 ; where to store text
mov si,bx
add si,2 ; source of text
cld
rep movsb ; copy name to rdbuf+6
mov byte ptr [di],0 ; null terminator
pop es
pop cx
jmp short getnam3 ; exit
getnam2:mov ax,[bx] ; get length of name
add ax,4 ; plus count and word pointer
add bx,ax ; point to next entry
pop cx
loop getnam1 ; look at next entry
getnam3:pop di
pop si
pop dx
pop cx
pop bx
ret
getname endp
; Renames macros \%0..\%9 by changing the first two characters of the name
; to be <null><taklev>. Used to preserve old \%n macros and not show them.
hidemac proc near
push bx
push cx
mov bx,offset mcctab+1 ; table of macro names, skip count
mov cl,mcctab ; number of entries
xor ch,ch
jcxz hidema3 ; z = empty table
hidema1:cmp word ptr [bx],3 ; name length, do three byte names
jne hidema2 ; ne = not three chars
cmp word ptr [bx+2],'%\' ; starts with correct prefix?
jne hidema2 ; ne = no
mov al,byte ptr [bx+4] ; third char of name
cmp al,'0' ; in digits?
jb hidema2 ; b = no
cmp al,'9'
ja hidema2
xor al,al ; prepare new prefix
mov ah,taklev ; of <null><taklev>
mov [bx+2],ax ; change the macro name
hidema2:mov ax,[bx] ; get length of name
add ax,4 ; plus count and word pointer
add bx,ax ; point to next entry
loop hidema1 ; look at next entry
hidema3:pop cx
pop bx
ret
hidemac endp
; Removes all current \%0..\%9 macros and renames <null><taklev> macros by
; changing the first two characters of the names \%n from <null><taklev> to
; be "\%". Used to recover old \%n macros from hidemac.
unhidemac proc near
push cx
push dx
push di
mov di,offset temptc ; temp macro name
mov word ptr [di+2],'%\' ; prefix for "\%n"
mov cl,'0' ; trailer for name
xor ch,ch ; null terminator
unhide1:mov [di+4],cx ; compose number
call remtab ; remove "\%n" macro
inc cl
cmp cl,'9' ; done?
jna unhide1 ; na = no, look at next entry
; now do rename of <null><taklev>n
unhide2:mov di,offset mcctab+1 ; table of macro names, skip count
mov cl,mcctab ; number of entries
xor ch,ch
jcxz unhide5 ; z = empty table
xor dl,dl ; macro prefix to examine
mov dh,taklev
unhide3:cmp word ptr [di],3 ; do only "<null><taklev>n" names
jne unhide4 ; ne = not three chars
mov al,[di+4] ; get char of name
cmp al,'0' ; is it a char in range for \%0..\%9?
jb unhide4 ; b = no
cmp al,'9' ; still in range?
ja unhide4 ; a = no
cmp word ptr [di+2],dx ; starts with <null><taklev> prefix?
jne unhide4 ; ne = no
mov [di+2],'%\' ; change the macro name back to "\%n"
unhide4:mov ax,[di] ; get length of name
add ax,4 ; plus count and word pointer
add di,ax ; point to next entry
loop unhide3 ; look at next entry
unhide5:pop di
pop dx
pop cx
ret
unhidemac endp
; DEFINE and ASSIGN macro commands
; Data structures comments. Macro name is stored in table mcctab as if we
; had used macro mkeyw, such as mkeyw 'mymac',offset my_definition.
; In detail: dw length of name
; db 'name'
; dw segment:0 of definition string
; Mcctab begins with a byte holding the number of macros in the table; one,
; IBM, is established at assembly time. Mcctab is 10*macmax bytes long.
; Pointer mccptr holds the offset of the next free byte in mcctab.
; Definition strings are stored in individually allocated memory as
; dw length of definition string below
; db 'definition string'
; A new definition is read into buffer rdbuf+2, where word rdbuf is reserved
; to hold the length of the macro's name during intermediate processing.
; If the definition is absent then the macro is removed from the tables.
;
; ASSIGN is equivalent to DEFINE, except in the definition string substitution
; variable names are expanded to their definitions.
; DEFINE does not expand substitution variables.
; Both commands will remove a first level curly brace pair if, and only if,
; the definition begins and ends with them (trailing whitespace is allowed).
ASSIGN PROC NEAR
mov defkind,0 ; flag command as ASSIGN, vs DEFINE
jmp short dodefcom ; common code
ASSIGN ENDP
DODEF PROC NEAR
mov defkind,1 ; flag command as DEFINE, vs ASSIGN
DODEFCOM:
mov comand.cmper,1 ; do not react to '\%' in macro name
mov ah,cmword
mov dx,offset rdbuf+2 ; buffer for macro name
mov word ptr rdbuf,0
mov comand.cmblen,length rdbuf ; length of analysis buffer
mov bx,offset macmsg
call comnd ; get macro name
jnc dodef1 ; nc = success
ret ; failure
dodef1: or ax,ax ; null entry?
jnz dodef2 ; nz = no
mov dx,offset ermes6 ; more parameters needed
jmp reterr
dodef2: mov bx,offset rdbuf+2 ; start of string
cmp word ptr [bx],'%\' ; \%<char> substitution variable?
jne dodef2b ; ne = no
cmp ax,2 ; count, but missing <char>?
ja dodef2a ; a = no
mov byte ptr [bx+2],'_' ; slip in an underscore
dodef2a:mov ax,3 ; limit to \%<char>, one char name
dodef2b:add bx,ax ; point to string terminator
mov byte ptr [bx],' ' ; replace null with space separator
mov word ptr [bx+1],0 ; terminator, in case no command
inc bx ; where definition will start
mov ax,cmdblen ; length of rdbuf
sub ax,bx ; - (current offset - offset rdbuf)
add ax,offset rdbuf ; ax = amount of buffer used
mov comand.cmblen,ax ; our new buffer length
mov al,defkind ; get ASSIGN/DEFINE flag
mov comand.cmper,al ; react (DEF) to '\%' in definition
mov ah,cmline ; get a line of text
mov dx,offset macmsg ; help, bx is buffer offset
push bx ; save starting offset
call comnd ; get macro definition text
pop bx
jnc dodef3 ; nc = success
ret ; failure
dodef3: add bx,ax ; end of command line
mov cx,bx
sub cx,offset rdbuf+2 ; length of command line
;; jmp dodecom
DODEF ENDP
; Make a macro table entry and allocate buffer space.
; Enter with rdbuf+2 et seq = <macro name><spaces><arg><spaces><arg> ...
; and CX = byte count of line, starting at rdbuf+2.
; Word rdbuf+0 computed here as length of keyword.
; Allocates memory based on analyzed size of command line, returns memory
; segment in macptr and in AX. Returns carry set if failure.
DODECOM PROC NEAR
push si ; macro name in rdbuf+1 et seq
push di ; cmd line length in deftemp
push es
push ds ; address data segment
pop es
mov deftemp,cx ; cmd line len, cx = running counter
mov rdbuf,0 ; number of chars in keyword so far
; uppercase the keyword, look for end
mov si,offset rdbuf+2 ; point at macro name itself
xor dx,dx ; a counter
cld ; strings go forward
dode2: lodsb ; get a byte
cmp al,'a' ; map lower case to upper
jb dode3
cmp al,'z'
ja dode3
sub al,'a'-'A'
mov [si-1],al ; uppercase if necessary
dode3: inc dx ; increment char count of keyword
cmp al,' ' ; is this the break character?
loopne dode2 ; no, loop thru rest of word
jne dode4 ; ne = did not end with break char
dec dx ; yes, don't count in length
dode4: mov di,offset rdbuf ; point at mac name length
mov [di],dx ; insert length in rdbuf
push dx ; save length around call
call remtab ; remove any duplicate keyword
; check for free space for keyword
pop ax ; keyword text length
add ax,4 ; plus count and word pointer
add ax,mccptr ; add to free space pointer
cmp ax,offset mcctab+mcclen ; enough room for name?
jb dode5 ; b = yes
mov dx,offset ermes1 ; too many macro names
pop es
pop di
pop si
jmp reterr
dode5: mov dx,si ; trim off leading/trailing spaces
call strlen
mov di,si ; si = definition source address
jcxz dode5a ; z = empty string
add di,cx ; start + length
dec di ; last char of string
std
mov al,' ' ; scan off trailing spaces
repe scasb
cld
mov byte ptr [di+2],0 ; plant new terminator
dode5a: mov dx,si
call strlen ; get new length into cx
cld
mov di,si ; scan after keyword name
mov al,' ' ; remove leading spaces in string
repe scasb
jne dode6 ; ne = have some text
pop es ; all spaces
pop di
pop si
clc ; success
ret
dode6: dec di ; offset auto increment of rep
mov si,di ; new start of string
mov dx,si ; source of definition text
call strlen ; get length of string into cx
mov deftemp,cx ; remember it here
; install new keyword
jcxz dode10 ; z = no def, exit now
mov bx,cx ; string length, in bytes
add bx,2+1+15 ; count + null term + round up
mov cl,4
shr bx,cl ; convert to paragraphs (divide by 16)
mov cx,bx ; remember desired paragraphs
mov ah,alloc ; allocate a memory block
int dos
jc dode12 ; c = error, not enough memory
cmp bx,cx ; obtained vs wanted
jae dode7 ; ae = enough
mov es,ax ; allocated segment
mov ah,freemem ; free it again
int dos
jmp short dode12 ; quit here
dode7: mov macptr,ax ; store new segment
mov es,ax ; segment of string
xor di,di ; offset of count word
mov cx,deftemp ; length of definition string
mov ax,cx
cld
stosw ; store length of string
rep movsb ; copy string
mov bx,offset mcctab
mov dx,offset rdbuf ; count word + name string
call addtab
dode10: mov ax,macptr ; return buffer segment to caller
pop es
pop di
pop si
clc ; success
ret
dode12: pop es ; no memory, clean stack
pop di
pop si
mov dx,offset ermes2 ; no room for definition
mov ah,prstr
int dos
stc
ret
DODECOM ENDP
; ASK <variable or macro name> <prompt string>
; Defines indicated variable/macro with text from user at keyboard or pipe
; (but not from a Take/macro). Prompt string is required.
; ASKQ does the same, but does not echo user's response.
ASKQ PROC NEAR
mov askecho,1 ; temp to flag as Quiet version
jmp short ask0 ; do common code
ASKQ ENDP
ASK PROC NEAR
mov askecho,0 ; temp to flag as echoing version
ask0: ; common code for ASK and ASKQ
mov dx,offset rdbuf+2 ; point to work buffer
mov word ptr rdbuf,0
mov bx,offset askhlp1 ; help
mov comand.cmper,1 ; do not expand variable name
mov ah,cmword ; get variable name
call comnd
jnc ask1 ; nc = success
ret ; failure
ask1: or ax,ax ; anything given?
jnz ask2 ; nz = yes
mov dx,offset ermes6 ; more parameters needed
jmp reterr
ask2: cmp word ptr rdbuf+2,'%\' ; \%<char> substitution variable?
jne ask2b ; ne = no
cmp al,2 ; but missing <char>
ja ask2a ; a = no
mov rdbuf+4,'_' ; slip in an underscore
ask2a: mov ax,3 ; limit to a single char
ask2b: mov bx,offset rdbuf+2 ; start of name
add bx,ax ; plus length of variable name
mov byte ptr [bx],' ' ; put space separator after name
inc ax ; count space
mov numhlp,ax ; remember length here
; get ASK command prompt string
mov bx,offset decbuf ; borrowed buffer for prompt
mov byte ptr [bx],0 ; safety terminator
mov dx,offset askhlp2
mov comand.cmblen,127 ; our buffer length
sub comand.cmblen,ax ; minus part used above
mov ah,cmline ; get prompt string
call comnd
jnc ask3 ; nc = success
ret ; failure
ask3: or ax,ax ; anything given?
jnz ask4 ; nz = yes
mov dx,offset ermes6 ; more parameters needed
jmp reterr
ask4: mov ax,takadr ; we could be in a macro or Take file
mov temp2,ax ; save Take address
mov al,taklev
xor ah,ah
mov temp1,ax ; and Take level
mov dx,size takinfo ; bytes for each current Take
mul dx ; times number of active Take/macros
sub takadr,ax ; clear Take address as if no
mov taklev,0 ; Take/macro were active so that
; user input is from kbd or pipe
mov word ptr [bx],0020h ; printing terminator for prompt
mov si,offset decbuf
mov di,si ; convert in-place
call cnvlin ; convert backslash items
mov dx,si ; converted prompt string, asciiz
call prompt ; use our prompt
mov bx,offset rdbuf+129 ; use this buffer for raw user input
mov word ptr [bx],0 ; insert terminator
mov dl,askecho ; get echo/quiet flag
mov comand.cmquiet,dl ; 0 if echoing
mov dx,offset askhlp3 ; help for user input
mov ah,cmline ; read user's input string
call comnd
mov comand.cmquiet,0 ; permit echoing again
mov cx,temp2
mov takadr,cx ; restore Take address
mov cx,temp1
mov taklev,cl ; restore Take level
jnc ask5 ; nc = success
ret ; Control-C, quit now
ask5: mov cx,ax ; length of entry
mov si,offset rdbuf+129 ; source string
mov di,offset rdbuf+2 ; start of variable name
add di,numhlp ; di points to final user string
push es ; save es
push ds
pop es ; set es to data segment
cld
jcxz ask8 ; z = empty
rep movsb ; copy string
ask8: xor al,al ; get null terminator
stosb ; plant it
pop es
mov dx,offset rdbuf+2 ; command buffer beginning
call strlen ; CX=len of <variable>< ><user string>
jmp DODECOM ; define the macro/variable and exit
ASK ENDP
; Initialize macro IBM at Kermit startup time
initibm proc near
mov si,offset ibmmac ; text of IBM macro
mov di,offset rdbuf+2 ; where command lines go
call strcpy ; copy it there
mov dx,di ; get length of command line
call strlen ; set cx to length, for dodecom
jmp dodecom ; now define the macro
initibm endp
; Open a disk based Take file buffer. Define macro named "<null>T<'taklev'>",
; in mcctab and allocate 128 byte uninitiated buffer for disk i/o. Leading null
; is to prevent user from employing the same name accidentally. Return seg
; of buffer in [takadr].takbuf and set [takadr].takptr to offset of first
; byte after leading count byte. Uses dodecom to make this macro.
; Return carry clear for success, carry set for failure.
TAKOPEN PROC NEAR
push ax
push bx
push cx
push dx
cmp taklev,maxtak ; room in take level?
jb takope1 ; b = yes
mov dx,offset ermes4 ; say too many Take files
mov ah,prstr ; display error message
int dos
stc ; set carry for failure
jmp short takope2
takope1:mov word ptr rdbuf,3 ; length of name, 3 bytes <null>Tn
mov rdbuf+2,0
mov rdbuf+3,'T' ; name of <null>Tn
mov al,taklev ; Take level digit
inc al ; for what will be next Take level
add al,'0' ; add ascii bias
mov rdbuf+4,al ; last of the name
mov rdbuf+5,' ' ; separate dummy definition
mov cx,tbufsiz ; fill with dummy non-blank data
push cx ; length of buffer, for dodecom
push di
push es ; save es
push ds ; set es to data segment
pop es
cld
mov al,'.' ; dummy fill pattern
mov di,offset rdbuf+6 ; definition text starts here
rep stosb ; store the pattern
pop es
pop di
pop cx ; get command length again
call dodecom ; define our Take macro
jc takope2 ; c = failure
xor ax,ax
xor cx,cx
cmp taklev,0 ; at top level now?
je takope3 ; e = yes
mov bx,takadr
mov ax,[bx].takargc ; get argument count
mov cx,[bx].takctr ; get COUNT
takope3:add takadr,size takinfo ; pointer to new Take structure
inc taklev
mov bx,takadr ; pointer to new Take structure
mov [bx].takargc,ax ; copy in old argc
mov [bx].takctr,cx ; copy in old count
mov ax,macptr ; segment of buffer
mov [bx].takbuf,ax ; segment of Take buffer
mov [bx].takcnt,tbufsiz-2 ; number of unread bytes
mov [bx].takptr,2 ; init pointer to definition itself
clc ; carry clear for success
takope2:pop dx
pop cx
pop bx
pop ax
ret
TAKOPEN ENDP
; Close Take file. Enter at Take level to be closed. Removes pseudo macro
; name <null>Tn and its buffer, closes disk file, pops Take level.
TAKCLOS PROC NEAR
cmp taklev,0 ; anything to close?
jle takclo3 ; le = no
push ax
push bx
push cx
mov al,taklev ; Take level digit
add al,'0' ; add ascii bias
mov temptc+2,0
mov temptc+3,'T'
mov temptc+4,al ; last of the name
push di
mov di,offset temptc ; pointer for remtab
call remtab ; remove possible old macro and buffer
pop di
mov bx,takadr ; point to Take structure
mov al,[bx].taktyp
cmp [bx].taktyp,0feh ; disk file?
jne takclo1 ; ne = no, no buffer to deallocate
mov bx,[bx].takhnd ; get file handle
mov ah,close2 ; close file
int dos
dec taklev ; pop disk file Take level
sub takadr,size takinfo ; get previous Take's address
jmp short takclo2
takclo1:dec taklev ; pop macro Take level
sub takadr,size takinfo ; get previous Take's address
cmp al,0ffh ; regular macro?
jne takclo2 ; ne = no, no unhiding necessary
call unhidemac ; rename previous \%n macros
takclo2:pop cx
pop bx
pop ax ; close prev Take/Macro if at EOF too
cmp taklev,0 ; Take/macro still open?
je takclo3 ; e = no
push bx
mov bx,takadr ; get it's address
cmp [bx].takcnt,0 ; is it at EOF?
pop bx
ja takclo3 ; a = no
jmp takclos ; yes, close it too
takclo3:ret
TAKCLOS ENDP
; POP/END command. Defend against command parser closing the Take/Macro at
; the end of file. Return optional trailing number in ERRORLEVEL (errlev).
POPCMD proc near
mov ah,cmword ; get optional error value
mov dx,offset rdbuf+1
mov rdbuf,'\' ; in case the user did not specify
mov bx,offset pophlp ; help on numerical argument
mov comand.cmcr,1 ; bare c/r's allowed
call comnd
mov comand.cmcr,0 ; restore normal state
jc popcmd3 ; c = failure
mov ah,cmeol ; confirm
call comnd
jc popcmd3
mov si,offset rdbuf
cmp byte ptr [si+1],'\' ; user specified?
jne popcmd1 ; ne = no, use ours
inc si ; yes, use theirs
popcmd1:call katoi ; convert to number in ax
jc popcmd2 ; c = not a number
mov errlev,al ; return value in ERRORLEVEL
mov kstatus,ax ; and in STATUS
popcmd2:mov al,oldtak ; Take level previous to this cmd
sub al,taklev ; minus Take level now
ja popcmd3 ; a = have exited macro already
jmp takclos ; close current Macro/Take
popcmd3:ret
POPCMD endp
; add an entry to a keyword table
; enter with bx = table address, dx = ptr to new entry, macptr = string seg
; mccptr = offset of free bytes in table mcctab.
; no check is made to see if the entry fits in the table.
addtab proc near
push cx
push si
push es
push bp
cld
mov ax,ds
mov es,ax ; address data segment
mov bp,bx ; remember where macro name table starts
mov cl,[bx] ; pick up length of table
xor ch,ch
inc bx ; point to actual table
jcxz addta4 ; cx = 0 if table is presently empty
addta1: push cx ; preserve count
mov si,dx ; point to entry
lodsw ; get length of new entry
mov cx,[bx] ; and length of table entry
cmp ax,cx ; are they the same?
lahf ; remember result of comparison
jae addta2 ; is new smaller? ae = no, use table length
mov cx,ax ; else use length of new entry
addta2: lea di,[bx+2] ; point to actual keyword
repe cmpsb ; compare strings
pop cx ; restore count
jb addta4 ; below, insert before this one
jne addta3 ; not below or same, keep going
sahf ; same. get back result of length comparison
jb addta4 ; if new len is smaller, insert here
jne addta3 ; if not same size, keep going
mov si,bx ; else this is where entry goes
jmp short addta6 ; no insertion required
addta3: mov ax,[bx] ; length of keyword
add bx,ax ; skip this entry
add bx,4 ; length word and 16 bit value
loop addta1 ; and keep looking
addta4: mov si,bx ; this is first location to move
mov di,bx
inc ds:byte ptr [bp] ; remember we're adding one
jcxz addta6 ; z = no more entries, forget this stuff
addta5: mov bx,[di] ; get length
lea di,[bx+di+4] ; end is origin + length + 4 for len, value
loop addta5 ; loop thru remaining keywords
mov cx,di
sub cx,si ; compute # of bytes to move
push si ; preserve loc for new entry
mov si,di ; first to move is last
dec si ; minus one
mov di,dx ; new entry
mov bx,[di] ; get length
lea di,[bx+si+4] ; dest is source + length of new + 4
std ; move backward
rep movsb ; move the table down (compress it)
cld ; put flag back
pop si
addta6: mov di,si ; this is where new entry goes
mov si,dx ; this is where it comes from
mov cx,[si] ; length of name
add cx,2 ; include count byte
add mccptr,cx ; update free space pointer: cnt+name
rep movsb ; insert new entry
mov ax,macptr ; and string address
stosw
add mccptr,2 ; plus string address
pop bp
pop es
pop si
pop cx
ret
addtab endp
; If new keyword matches an existing one then remove existing keyword,
; its string definition, compress tables mcctab and macbuf, readjust string
; pointers for each macro name, reduce number of macro table entries by one.
; Enter with DI pointing at length word of mac name (followed by mac name).
; Otherwise, exit with no changes. 13 June 1987 [jrd]
remtab proc near
push ax
push bx
push cx
push si
push di
mov bx,temp ; preserve
push bx
mov bx,offset mcctab+1 ; table of macro keywords
mov temp,0 ; temp = current keyword
cmp byte ptr mcctab,0 ; any macros defined?
jne remta1 ; ne = yes
jmp remtax ; else exit now
remta1: ; match table keyword and text word
mov si,di ; pointer to user's cnt+name
mov cx,[si] ; length of user's macro name
add si,2 ; point to new macro name
cmp cx,[bx] ; compare length vs table keyword
jne remta4 ; ne = not equal lengths, try another
push si ; lengths match, how about spelling?
push bx
add bx,2 ; point at start of keyword
remta2: mov ah,[bx] ; keyword char
mov al,[si] ; new text char
cmp al,ah ; test characters
jne remta3 ; ne = no match
inc si ; move to next char
inc bx
loop remta2 ; loop through entire length
remta3: pop bx
pop si
jcxz remta6 ; z: cx = 0, exit with match;
; else select next keyword
remta4: inc temp ; number of keyword to test next
mov cx,temp
cmp cl,mcctab ; all done? Recall, temp starts at 0
jb remta5 ; b = not yet
jmp remtax ; exhausted search, unsuccessfully
remta5: mov ax,[bx] ; cnt (keyword length from macro)
add ax,4 ; skip count and word pointer
add bx,ax ; bx = start of next keyword slot
jmp short remta1 ; do another comparison
; new name already present as a macro
remta6: cld ; clear macro string and macro name
push ds
pop es ; set es to data segment
mov temp,bx ; save ptr to found keyword
mov ax,[bx] ; cnt (keyword length of macro)
add ax,2 ; skip cnt
add bx,ax ; point to string segment field
add ax,2 ; count segment field bytes
sub mccptr,ax ; readjust free space ptr for names
push bx
push es
mov es,[bx] ; segment of string
mov ax,ds ; check for being in our data segment
cmp ax,[bx] ; same as our data seg?
je remta7 ; e = yes, don't free that
mov ah,freemem ; free that memory block
int dos
remta7: pop es
pop bx
; clear keyword table mcctab
add bx,2 ; compute source = next keyword
mov si,bx ; address of next keyword
mov di,temp ; address of found keyword
mov cx,offset mcctab+mcclen ; address of buffer end
sub cx,si ; amount to move
jcxz remtax ; cx = 0 means none
rep movsb ; move down keywords (deletes current)
dec mcctab ; one less keyword
remtax: pop temp ; recover temp variable
pop di
pop si
pop cx
pop bx
pop ax
ret
remtab endp
; Common Get keyword + Get Confirm sequence. Call with dx = keyword table,
; bx = help message offset. Returns result in BX. Modifies AX, BX.
; Returns carry clear if sucessful else carry set. Used in many places below.
keyend proc near
mov ah,cmkey
call comnd
jnc keyend1 ; nc = success
ret ; failure
keyend1:push bx ; save returned results around call
mov ah,cmeol ; get c/r confirmation
call comnd
pop bx ; recover keyword 16 bit value
ret ; return with carry from comnd
keyend endp
srvdsa proc near ; DISABLE Server commands
mov dx,offset srvdetab
mov bx,offset sdshlp
call keyend
jc srvdsa1 ; c = failure
or denyflg,bx ; turn on bit (deny) for that item
srvdsa1:ret
srvdsa endp
srvena proc near ; ENABLE Server commands
mov dx,offset srvdetab ; keyword table
mov bx,offset sdshlp ; help on keywords
call keyend
jc srvena1 ; c = failure
not bx ; invert bits
and denyflg,bx ; turn off (enable) selected item
srvena1:ret
srvena endp
; This is the SET command
; Called analyzers return carry clear for success, else carry set.
SETCOM PROC NEAR ; Dispatch all SET commands from here
mov kstatus,kssuc ; global status, success
mov dx,offset settab ; Parse a keyword from the set table
mov bx,offset sethlp
mov ah,cmkey
call comnd
jc setcom1 ; c = failure
jmp bx ; execute analyzer routine
setcom1:ret
SETCOM endp
SETATT PROC NEAR ; Set attributes on | off
mov dx,offset atttab
xor bx,bx
mov ah,cmkey
call comnd
jc setatt3 ; c = failure
mov dx,bx ; hold results in dx
cmp dl,0ffh ; ON/OFF (all of them)?
je setatt1 ; e = yes
push dx
mov dx,offset ontab ; get on/off state
xor bx,bx
mov ah,cmkey
call comnd
pop dx
jc setatt3 ; c = failure
mov dh,bl ; store on/off state in dh
setatt1:push dx
mov ah,cmeol
call comnd
pop dx
jc setatt3
mov al,flags.attflg ; current flags
not dl ; all but those affected
and al,dl ; turn off affected flags
or dh,dh ; off (dh = 0)?
jz setatt2 ; z = yes
not dl ; affected flags back again as ones
or al,dl ; turn on affected flags
setatt2:mov flags.attflg,al
setatt3:ret
SETATT ENDP
; SET BAUD or SET SPEED
; See system dependent routine BAUDST in file MSXxxx.ASM
; SET BELL on or off
BELLST PROC NEAR
mov dx,offset ontab ; on/off table
xor bx,bx ; help
call keyend
jc bellst1 ; c = failure
mov flags.belflg,bl
bellst1:ret
BELLST ENDP
; SET BLOCK-CHECK
BLKSET PROC NEAR
mov dx,offset blktab ; table
xor bx,bx ; help, use table
call keyend
jc blkset1 ; c = failure
mov dtrans.chklen,bl ; use this char as initial checksum
blkset1:ret
BLKSET ENDP
; Set port addresses for COM1 .. COM4 at Kermit initialization time via
; Environment. Called by command parser while doing Environment reading in
; mssker.asm and via SET COM1 .. SET COM4.
COM1PORT proc near
mov bx,0 ; offset of com1 port address
jmp short comport
COM1PORT endp
COM2PORT proc near
mov bx,2 ; offset of com2 port address
jmp short comport
COM2PORT endp
COM3PORT proc near
mov bx,4 ; offset of com3 port address
jmp short comport
COM3PORT endp
COM4PORT proc near
mov bx,6 ; offset of com4 port address
;; jmp comport
COM4PORT endp
COMPORT proc near ; worker for above
push bx ; save offset
mov dx,offset rdbuf+1
mov word ptr rdbuf,0
mov bx,offset comhlp
mov ah,cmword ; get port address number
call comnd
jnc compor3
pop bx ; fail
ret
compor3:mov numerr,0 ; no error message
mov min,100h ; smallest number
mov max,0fff0h ; largest magnitude
mov numhlp,0 ; help
call numwd ; parse this word
jnc compor4 ; nc = success, value in ax
pop bx
ret
compor4:mov temp1,ax ; save port address
mov dx,offset rdbuf+1
mov word ptr rdbuf,0
mov bx,offset irqhlp
mov temp2,0
mov ah,cmword ; read IRQ
call comnd
jnc compor5
pop bx
ret
compor5:push ax
mov ah,cmeol ; get command confirmation
call comnd
pop ax
jnc compor5a ; nc = success
ret
compor5a:or ax,ax ; anything given?
jz compor7 ; z = no
mov numhlp,0 ; help
mov numerr,0 ; no error message
mov min,2 ; smallest number
mov max,15 ; largest magnitude
call numwd ; parse this word
jnc compor6 ; nc = success
pop bx
ret
compor6:mov temp2,ax ; save IRQ
compor7:pop bx ; recover offset
cmp word ptr machnam,'BI' ; check for "IBM-PC"
jne compor1 ; ne = not this name, fail
cmp word ptr machnam+2,'-M'
jne compor1
cmp word ptr machnam+4,'CP'
jne compor1
push es
mov al,flags.comflg ; current comms port
dec al ; count from 0, as per Bios
shl al,1 ; double to use word index of Bios
cmp al,bl ; using this port now?
jne compor2 ; ne = no
call serrst ; reset the port
compor2:mov cx,40h ; segment 40h
mov es,cx
mov ax,temp1 ; port address
mov es:[bx],ax ; set port address
pop es
shr bl,1 ; coms port offset 0,2,4,6 to 0,1,2,3
mov ax,temp2 ; IRQ
mov portirq[bx],al
clc
compor1:ret
COMPORT endp
; SET COUNTER number for script IF COUNTER number <command>
TAKECTR PROC NEAR
mov min,0 ; get decimal char code
mov max,65535 ; range is 0 to 65535 decimal
mov numhlp,offset takchlp ; help message
mov numerr,0 ; error message
call num0 ; convert number, return it in ax
jc takect2 ; c = error
push ax ; save numerical code
mov ah,cmeol
call comnd ; get a confirm
pop ax ; recover ax
jc takect2 ; c = failure
cmp taklev,0 ; in a Take file?
je takect4 ; e = no
push bx
mov bx,takadr
mov [bx].takctr,ax ; set COUNT value
pop bx
clc ; success
takect2:ret
takect4:mov dx,offset takcerr ; say must be in Take file
jmp reterr ; display msg and return carry clear
TAKECTR ENDP
; SET DEBUG {OFF | ON | SESSSION | PACKETS}
DEBST PROC NEAR
mov dx,offset debtab
mov bx,offset debhlp
call keyend
jnc debst1 ; nc = success
ret ; failure
debst1: or flags.debug,bl ; set the mode, except for Off
or bx,bx ; OFF?
jnz debst2 ; nz = no
mov flags.debug,bl ; set the DEBUG flags off
debst2: clc ; success
ret
DEBST ENDP
; SET DESTINATION of incoming files
DESSET PROC NEAR
mov dx,offset destab
xor bx,bx
call keyend
jc desset1 ; c = failure
mov flags.destflg,bl ; set the destination flag
desset1:ret
DESSET ENDP
; SET DEFAULT-DISK for sending/receiving, etc
; See cwdir in file mssker
; SET DELAY seconds Used only for SEND command in local mode
SETDELY PROC NEAR
mov min,0 ; smallest acceptable value
mov max,63 ; largest acceptable value
mov numhlp,offset delyhlp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc setdly1 ; c = error
mov trans.sdelay,al
setdly1:ret ; success or failure
SETDELY ENDP
; SET DISPLAY Quiet/Regular/Serial/7-Bit/8-Bit (inverse of Set Remote on/off)
; Accepts two keywords in one command
disply proc near
mov ah,cmkey
mov dx,offset distab
mov bx,offset dishlp
call comnd
jnc displ0 ; nc = success
ret ; return failure
displ0: mov temp1,bx ; save parsed value
mov temp2,0ffffh ; assume no second keyword
mov comand.cmcr,1 ; bare CR's are allowed
mov ah,cmkey ; parse for second keyword
mov dx,offset distab
mov bx,offset dishlp
call comnd
jc displ1 ; no keyword
mov temp2,bx ; get key value
displ1: mov comand.cmcr,0 ; bare CR's are not allowed
mov ah,cmeol
call comnd ; confirm
jnc displ2 ; nc = success
ret ; failure
displ2: mov ax,temp1 ; examine first key value
call dispcom ; do common code
mov ax,temp2 ; examine second key value
; jmp dispcom ; finish in common code
dispcom:or ax,ax ; check range
jle dispc3 ; le = not legal, ignore
cmp al,7 ; 7-8 bit value?
jge dispc2 ; ge = yes
and flags.remflg,not(dquiet+dregular+dserial)
or flags.remflg,al ; set display mode
clc ; success
ret ; check next key value
dispc2: cmp al,8 ; set 8-bit wide display?
ja dispc3 ; a = bad value
and flags.remflg,not d8bit ; assume want 7 bit mode
cmp al,7 ; really want 7 bit mode?
je dispc3 ; e = yes
or flags.remflg,d8bit ; set 8 bit flag
dispc3: clc ; success
ret ; end of display common code
disply endp
; Set Dump filename for saving screen images on disk.
; Puts filename in global string dmpname
setdmp proc near
mov dx,offset rdbuf ; work area
mov rdbuf,0 ; clear it
mov bx,offset dmphlp ; help message
mov ah,cmword ; allow paths
call comnd
jc setdmp2 ; c = failure
mov ah,cmeol
call comnd
jc setdmp2 ; c = failure
mov dx,offset rdbuf ; assume we will use this text
call strlen ; filename given?
mov si,dx ; for strcpy
or cx,cx ; length of user's filename
jg setdmp1 ; g = filename is given
mov si,offset dmpdefnam ; no name, use default instead
setdmp1:mov di,offset dmpname ; copy to globally available loc
call strcpy
clc
setdmp2:ret
setdmp endp
; Set DUPLEX {FULL, HALF}
setdup proc near
xor bx,bx
mov dx,offset duptab
call keyend
jc setdup1 ; c = failure
mov si,portval
mov [si].duplex,bl ; set value
mov [si].ecoflg,0 ; turn off local echoing
or bl,bl ; full duplex?
jz setdup1 ; z = yes
mov [si].floflg,0 ; no flow control for half duplex
mov [si].ecoflg,1 ; turn on local echoing
call serrst ; reset port so opening uses above
setdup1:ret
setdup endp
; SET EOF
SETEOF PROC NEAR
xor bx,bx
mov dx,offset seoftab
call keyend
jc seteof1 ; c = failure
mov flags.eofcz,bl ; set value
seteof1:ret
SETEOF ENDP
; SET End-of-Packet char (for Sent packets)
; Archic, here for downward compatibility
EOLSET PROC NEAR
mov stflg,'S' ; set send/receive flag to Send
jmp sreol ; use Set Send/Rec routine do the work
EOLSET ENDP
; SET ERRORLEVEL number
SETERL PROC NEAR
mov numhlp,offset erlhlp ; help
mov numerr,0 ; error message
mov min,0 ; smallest number
mov max,255 ; largest magnitude
call num0 ; parse numerical input
jc seterl1 ; c = error
mov errlev,al ; store result
clc
seterl1:ret
SETERL ENDP
; SET ESCAPE character.
; Accept literal control codes and \### numbers. [jrd] 18 Oct 1987
ESCSET PROC NEAR
mov ah,cmword
mov dx,offset rdbuf ; work space
mov word ptr rdbuf,0 ; clear it
mov bx,offset eschlp ; help
call comnd
jc escse2 ; c = failure
or ax,ax ; anything given?
jnz escse1 ; nz = yes
mov dx,offset ermes6 ; more parameters needed
jmp reterr
escse1: mov ah,cmeol ; get a confirm
call comnd
jc escse2 ; c = failure
mov si,offset rdbuf ; source of chars
call katoi ; convert escaped numbers to binary
cmp ax,spc ; is it a control code?
jae escse3 ; ae = no, complain
or ax,ax ; non-zero too?
jz escse3 ; z = zero
mov trans.escchr,al ; save new escape char code
clc
escse2: ret
escse3: mov dx,offset escerr
jmp reterr
ESCSET ENDP
; SET FILE {DISPLAY, WARNING, TYPE, CHARACTER-SET}
SETFILE proc near
mov dx,offset setfitab ; SET FILE table
xor bx,bx
mov ah,cmkey
call comnd
jc setfix ; c = failure
or bl,bl ; Warning?
jnz setfi1 ; nz = no
; entry point for old SET WARNING
FILWAR: mov dx,offset warntab ; warning table, on, off, no-super
xor bx,bx
call keyend
jc setfix ; c = failure
mov flags.flwflg,bl ; set the filewarning flag
ret
setfi1: cmp bl,1 ; SET FILE CHARACTER-SET?
jne setfi2 ; ne = no
mov dx,offset setchtab ; table of char sets
xor bx,bx
call keyend ; get the set id
jc setfix ; c = error
mov flags.chrset,bx ; save the id
cmp bx,866 ; setting CP866?
jne setfi1a ; ne = no
cmp dtrans.xchset,2 ; using TRANSFER of Cryillic?
je setfi1a ; e = yes
mov dtrans.xchset,2 ; force TRANSFER of Cyrillic
mov trans.xchset,2
mov ah,prstr
mov dx,offset setchmsg ; show warning
int dos
setfi1a:clc
ret
setfi2: cmp bl,2 ; SET FILE TYPE?
jne setfi3 ; ne = 3
mov dx,offset xftyptab ; table of types
xor bx,bx
call keyend
jc setfix ; c = error
mov dtrans.xtype,bl ; store transfer type
mov trans.xtype,bl ; store transfer type
ret
setfi3: cmp bl,3 ; SET FILE DISPLAY?
jne setfix ; ne = no
mov dx,offset distab2 ; table
xor bx,bx
call keyend
jc setfix ; c = failure
and flags.remflg,not(dquiet+dregular+dserial)
or flags.remflg,bl ; set display mode
clc
setfix: ret
SETFILE endp
; SET FLOW-CONTROL {NONE, XONXOFF, RTS/CTS}
FLOSET PROC NEAR
mov dx,offset flotab
xor bx,bx
call keyend
jc floset3 ; c = failure
mov si,portval
mov ax,floxon ; xon/xoff pair
cmp bx,1 ; using none or xon/xoff?
jb floset1 ; b = none
je floset2 ; e = xon/xoff
cmp flags.comflg,4 ; UART?
ja floset4 ; a = no, error
floset1:xor ax,ax ; clear chars for RTS/CTS and none
floset2:mov [si].flowc,ax ; flow control values
mov [si].floflg,bl ; flow control kind
call serrst ; reset port so opening uses above
clc
floset3:ret
floset4:mov dx,offset ermes7 ; error message
jmp reterr
FLOSET ENDP
; SET HANDSHAKE
; Add ability to accept general decimal code.
HNDSET PROC NEAR
mov dx,offset hndtab ; table to scan
mov bx,offset hnd1hlp ; help message
mov ah,cmkey
call comnd
jc hnd2 ; c = failure
cmp bl,0ffh ; want a general char code?
jne hnd1 ; ne = no
mov min,0 ; get decimal char code
mov max,31 ; range is 0 to 31 decimal
mov numhlp,offset ctlhlp ; help message
mov numerr,0 ; error message
call num0 ; convert number, return it in ax
jc hnd2 ; c = error
mov bx,ax ; recover numerical code
hnd1: push bx ; handshake type
mov ah,cmeol
call comnd ; get a confirm
pop bx ; recover bx
jc hnd2 ; c = failure
mov si,portval
or bl,bl ; setting handshake off?
jz hnd0 ; z = yes
mov [si].hndflg,1 ; turn on handshaking
mov [si].hands,bl ; use this char as the handshake
clc ; success
ret
hnd0: mov [si].hndflg,bl ; no handshaking
clc ; success
hnd2: ret
HNDSET ENDP
; SET INCOMPLETE file disposition
ABFSET PROC NEAR
mov dx,offset abftab
xor bx,bx
call keyend
jc abfset1 ; c = failure
mov flags.abfflg,bl ; Set the aborted file flag
abfset1:ret
ABFSET ENDP
;
; Set Input commands (default-timeout, timeout-action, case, echo)
; By Jim Strudevant [jrs]
INPSET PROC NEAR
mov ah,cmkey ; key word
mov dx,offset inptab ; from inputtable
xor bx,bx ; no hints
call comnd ; get the word
jc inpset1 ; c = failure
jmp bx ; do the sub command
inpset1:ret
;
; Set Input Default-timeout in seconds
;
inptmo: mov numhlp,offset intoms ; help
mov numerr,0 ; error message
mov min,0 ; smallest number
mov max,-1 ; largest magnitude
call num0 ; parse numerical input
jc inptmo1 ; c = error
mov script.indfto,ax ; store result
inptmo1:ret
;
; Set Input Timeout action (proceed or quit)
;
inpact: mov dx,offset inactb ; from this list
xor bx,bx ; no hints
call keyend ; get it
jc inpact1 ; c = failure
mov script.inactv,bl ; save the action
inpact1:ret
;
; Set Input Echo on or off
;
inpeco: mov dx,offset ontab ; from this list
xor bx,bx ; no hints
call keyend ; get it
jc inpeco1 ; c = failure
mov script.inecho,bl ; save the action
inpeco1:ret
;
; Set Input Case observe or ignore
;
inpcas: mov dx,offset incstb ; from this list
xor bx,bx ; no hints
call keyend ; get it
jc inpcas1 ; c = failure
mov script.incasv,bl ; save the action
inpcas1:ret
INPSET ENDP
; Set length of script buffer for INPUT/REINPUT at Kermit initialization
; time via Environment. Called by command parser while doing Environment
; reading in mssker.asm. Do not call after Kermit has initialized.
SETINPBUF proc near
mov scpbuflen,128 ; store default buffer length
mov numhlp,0 ; no help
mov numerr,0 ; no error message
mov min,2 ; smallest number (must be non-zero)
mov max,64535 ; largest magnitude (16 bits worth)
call num0 ; parse numerical input
jc setinpbx ; c = error
mov scpbuflen,ax ; store result
clc
setinpbx:ret
SETINPBUF endp
; SET KEY
; Jumps to new Set Key routine
setkey proc near
cmp stkadr,0 ; keyboard translator present?
je setk4 ; e = no, use this routine
mov bx,stkadr ; yes, get offset of procedure
jmp bx ; jump to keyboard translator
setk4: mov dx,offset ermes5
jmp reterr ; else print error message
setkey endp
; SET LOCAL-ECHO {ON | OFF}
LCAL PROC NEAR
mov dx,offset ontab
xor bx,bx
call keyend
jc lcal1 ; c = failure
mov si,portval
mov [si].ecoflg,bl ; Set the local echo flag
lcal1: ret
LCAL ENDP
; LOG {PACKETS | SESSION | TRANSACTION} filename
setcpt proc near
mov dx,offset logtab ; kinds of logging
mov bx,offset loghlp ; help on kind of logging
mov ah,cmkey ; parse keyword
call comnd
jnc setcp20 ; nc = success
ret ; failure
setcp20:mov numhlp,bx ; save the parsed value
mov dx,offset rdbuf ; holds the complete filename
mov rdbuf,0 ; clear buffer
mov bx,offset filhlp ; ask for filename
mov ah,cmword ; allow paths
call comnd
jnc setcp21 ; nc = success
ret ; failure
setcp21:mov ah,cmeol
call comnd ; get a confirm
jnc setcp22 ; nc = success
ret ; failure
setcp22:mov bx,numhlp ; recover kind of logging
mov dx,offset rdbuf ; length of filename to cx
call strlen ; length of given filename
test bl,logpkt ; packet logging?
jz setcp2 ; z = no, try others
mov dx,offset lpktnam ; filename
jcxz setcp1 ; z = no filename given
mov si,offset rdbuf ; get new name
mov di,dx ; destination
call strcpy ; replace old name
setcp1: cmp ploghnd,-1 ; packet log file already open?
je setcp6 ; e = no, open it
jmp setcp16 ; say file is open already
setcp2: test bl,logses ; session logging?
jz setcp4 ; z = no, try others
mov dx,offset lsesnam ; use default name
jcxz setcp3 ; z = no filename given
mov si,offset rdbuf ; get new name
mov di,dx ; destination
call strcpy ; replace old name
setcp3: cmp sloghnd,-1 ; transaction file already open?
je setcp6 ; e = no, open it
jmp setcp16 ; say file is open already
setcp4: test bl,logtrn ; transaction logging?
jz setcp14 ; z = no, error
mov dx,offset ltranam ; use default name
jcxz setcp5 ; z = no filename given
mov si,offset rdbuf ; get new name
mov di,dx ; destination
call strcpy ; replace old name
setcp5: cmp tloghnd,-1 ; transaction file already open?
je setcp6 ; e = no, open it
jmp setcp16 ; say file is open already
setcp6: mov ax,dx ; place for filename for isfile
call isfile ; does file exist already?
jc setcp7 ; c = does not exist so use create
test byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
jnz setcp14 ; nz = no, use error exit
mov ah,open2 ; open existing file
mov al,1+1 ; for writing and reading
int dos
jc setcp14 ; if carry then error
mov bx,ax ; file handle for seeking
xor cx,cx ; high order displacement
xor dx,dx ; low order part of displacement
mov ah,lseek ; seek to EOF (to do appending)
mov al,2 ; says to EOF
int dos
jmp short setcp8
setcp7: test filtst.fstat,80h ; access problem?
jnz setcp14 ; nz = yes, stop here
mov ah,creat2 ; function is create
mov cx,20H ; turn on archive bit
int dos ; create the file, DOS 2.0
jc setcp14 ; if carry bit set then error
mov bx,ax ; file handle
setcp8: cmp numhlp,logpkt ; packet logging?
jne setcp9 ; ne = no
mov ploghnd,bx ; save transaction log handle here
jmp short setcp12
setcp9: cmp numhlp,logses ; session logging?
jne setcp10 ; ne = no
mov sloghnd,bx ; save session log handle here
jmp short setcp12
setcp10:mov tloghnd,bx ; save transaction log handle here
setcp12:mov ax,numhlp ; kind of Logging
or flags.capflg,al ; accumulate kinds of logging
clc ; success
ret
setcp14:mov dx,offset errcap ; give error message
jmp reterr ; and display it
setcp16:mov ah,prstr ; file already open
mov dx,offset erropn
int dos
clc ; return success
ret
setcpt endp
; SET MODE LINE
MODL PROC NEAR
mov dx,offset ontab ; parse an on or off
xor bx,bx ; no special help
call keyend
jc modl1 ; c = failure
mov flags.modflg,bl ; set flag appropriately
modl1: ret
MODL ENDP
; SET PARITY
SETPAR PROC NEAR
mov dx,offset partab ; parity table
xor bx,bx
call keyend
jnc setp1 ; nc = success
ret
setp1: mov si,portval
mov [si].parflg,bl ; store the parity flag
call serrst ; reset port so opening uses above
clc
ret
SETPAR ENDP
; Set Print filename for writing material to printers.
; Puts filename in global string prnname
setprn proc near
mov dx,offset rdbuf ; work area
mov rdbuf,0 ; clear it
mov bx,offset prnhlp ; help message
mov ah,cmword ; allow paths
call comnd
jc setprn3 ; c = failure
mov ah,cmeol
call comnd
jc setprn3 ; c = failure
mov dx,offset rdbuf ; assume we will use this text
call strlen ; filename given?
mov si,dx ; for strcpy
or cx,cx ; length of user's filename
jg setprn1 ; g = filename is given
mov si,offset prndefnam ; no name, use default instead
setprn1:mov di,offset prnname ; copy to globally available loc
call strcpy
cmp prnhand,0 ; handle already in use?
jle setprn2 ; le = no
call pntflsh ; flush current buffer
mov bx,prnhand ; close the file now
cmp bx,4 ; don't close DOS PRN
je setprn2 ; e = already available
mov ah,close2
int dos
setprn2:call prnopen ; open printer now, may set carry
jnc setprn3 ; nc = success
mov ah,prstr
mov dx,offset prnerr ; say can't open the file
int dos
mov si,offset prndefnam ; use default name as fallback
mov di,offset prnname ; copy to globally available loc
call strcpy
mov prnhand,4 ; declare handle to be DOS PRN
setprn3:ret
setprn endp
; SET PROMPT Allow user to change the "Kermit-MS>" prompt
; {string} and \number notation permitted to represent special chars.
; String will be made asciiz
PROMSET PROC NEAR
mov ah,cmline
mov bx,offset rdbuf ; Read in the prompt
mov word ptr [bx],0 ; clear buffer
mov dx,offset prmmsg
call comnd
jc prom2 ; c = failure
or ax,ax ; prompt string?
jnz prom0 ; nz = yes
mov ax,offset kerm ; no, restore default prompt
jmp short prom1
prom0: push si ; parse \### constants into
push di ; 1 byte binary numbers inline
mov si,offset rdbuf ; source = new prompt string
mov byte ptr [si-1+length rdbuf],0 ; plant null terminator
mov di,offset prm ; destination
call cnvlin ; convert \### in string to binary
pop di
pop si
mov bx,cx ; get byte count
mov prm[bx],0 ; insert null terminator
mov ax,offset prm
prom1: mov prmptr,ax ; remember it
clc ; success
prom2: ret
PROMSET ENDP
; SET SERVER {LOGIN username password | TIMEOUT}
SETSRV PROC NEAR
mov dx,offset srvtab ; set server table
xor bx,bx ; use table for help
mov ah,cmkey ; get keyword
call comnd
jnc setsrv1 ; c = success
ret
setsrv1:cmp bl,1 ; Login?
jne setsrv2 ; ne = no
test flags.remflg,dserver ; acting as a server now?
jz setsrv3 ; z = no
stc ; fail
ret
setsrv3:mov dx,offset rdbuf ; where to store local username
mov bx,offset luserh ; help
mov comand.cmblen,16 ; buffer length
mov ah,cmword ; get username
call comnd
jc setsrvx
mov bx,offset rdbuf+30 ; where to store local password
mov dx,offset lpassh ; help
mov comand.cmblen,16 ; buffer length
mov ah,cmline ; get password, allow spaces
call comnd
jc setsrvx
mov si,offset rdbuf ; only now do we transfer to the
mov di,offset luser ; active buffers
call strcpy
mov si,offset rdbuf+30
mov di,offset lpass
call strcpy
clc
ret
setsrv2:mov min,0 ; Timeout, smallest acceptable value
mov max,255 ; largest acceptable value, one byte
mov numhlp,offset srvthlp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc setsrvx ; c = error
mov srvtmo,al ; store timeout value
clc ; success
setsrvx:ret
SETSRV ENDP
; SET RETRY value. Changes the packet retry limit.
RETRYSET PROC NEAR
mov min,1 ; smallest acceptable value
mov max,63 ; largest acceptable value
mov numhlp,offset retryhlp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc retrys1 ; c = error
mov maxtry,al
retrys1:ret
RETRYSET ENDP
; Set number of screens in terminal emulator rollback buffer at Kermit
; initialization time via Environment. Called by command parser while doing
; Environment reading in mssker.asm. Do not call after Kermit has initialized.
SETROLLB proc near
mov npages,10 ; default number of rollback screens
mov numhlp,0 ; no help
mov numerr,0 ; no error message
mov min,0 ; smallest number
mov max,130 ; largest magnitude (16 bits worth)
call num0 ; parse numerical input
jc setrol1 ; c = error
mov npages,ax ; store result
clc
setrol1:ret
SETROLLB endp
; SET TAKE-ECHO on or off
TAKSET PROC NEAR
mov dx,offset ontab
xor bx,bx
call keyend
jc takset1 ; c = failure
mov flags.takflg,bl
takset1:ret
TAKSET ENDP
; SET TIMER on or off during file transfer
TIMSET PROC NEAR
mov dx,offset ontab
xor bx,bx
call keyend
jc timset1 ; c = failure
mov flags.timflg,bl
timset1:ret
TIMSET ENDP
; SET WINDOW number of windows
WINSET PROC NEAR
mov min,1 ; smallest acceptable value
mov max,maxwind ; largest acceptable value
mov numhlp,offset winhelp ; help message
mov numerr,0 ; complaint message
call num0 ; parse numerical input
jc winse5 ; c = error
mov dtrans.windo,al ; store default window size
mov trans.windo,al ; and in active variable for makebuf
call makebuf ; clear old buffers
cbw
mov cx,ax
mov ax,maxpack ; length of main DATA buffer
xor dx,dx ; extended numerator
cmp cx,1 ; zero means one here
jbe winse1
div cx ; get new max packet length into ax
winse1: cmp trans.slong,ax ; need to shorten sent packets?
jbe winse2 ; be = no
mov trans.slong,ax ; set send value
mov cl,dtrans.spsiz ; default regular packet send size
xor ch,ch
cmp ax,cx ; within normal packet range?
ja winse2 ; a = no
mov trans.spsiz,al ; yes, update regular pkt size too
winse2: cmp trans.rlong,ax ; need to shorten received pkts too?
jbe winse4 ; be = no
mov trans.rlong,ax ; set receive value
mov cl,dtrans.rpsiz ; default regular packet receive size
xor ch,ch
cmp ax,cx ; within normal packet range?
ja winse4 ; a = no
mov trans.rpsiz,al ; yes, update regular pkt size too
winse4: clc ; success
winse5: ret
WINSET ENDP
; SET SEND parameters
SENDSET PROC NEAR
mov stflg,'S' ; Setting SEND parameter
mov dx,offset stsrtb ; Parse a keyword
xor bx,bx ; no specific help
mov ah,cmkey
call comnd
jc sendset1 ; c = failure
jmp bx ; do the action routine
sendset1:ret
SENDSET ENDP
; SET RECEIVE parameters
recset: mov stflg,'R' ; Setting RECEIVE paramter
mov dx,offset stsrtb ; Parse a keyword
xor bx,bx ; no specific help
mov ah,cmkey
call comnd
jc recset1 ; c = failure
jmp bx ; do the action routine
recset1:ret
remset proc near ; Set REMOTE ON/OFF
mov dx,offset ontab
mov bx,offset remhlp
call keyend
jc remset2 ; c = failure
and flags.remflg,not (dquiet+dserial+dregular) ; no display bits
or bl,bl ; want off state? (same as regular)
jz remset1 ; z = yes
or flags.remflg,dquiet ; else on = quiet display
clc
ret
remset1:or flags.remflg,dregular ; off = regular display
clc
remset2:ret
remset endp
; SET Send and Receive End-of-Packet char
sreol PROC NEAR
mov min,0 ; lowest acceptable value
mov max,1FH ; largest acceptable value
mov numhlp,offset ctlhlp ; reuse help message
mov numerr,0 ; error message address
call num0 ; get numerical input
jc sreol3 ; c = error
cmp stflg,'S' ; setting SEND paramter?
je sreol1
mov trans.reol,al
jmp short sreol2
sreol1: mov dtrans.seol,al
sreol2: mov ah,dtrans.seol
mov trans.seol,ah
clc
sreol3: ret
sreol ENDP
; SET SEND and RECEIVE start-of-header
srsoh: mov min,0
mov max,1FH
mov numhlp,offset ctlhlp ; Reuse help message
mov numerr,0 ; error message
call num0 ; Common routine for parsing numerical input
jc srsoh2 ; c = error
cmp stflg,'S' ; Setting SEND paramter?
je srsoh1
mov trans.rsoh,al ; set Receive soh
clc ; success
ret
srsoh1: mov trans.ssoh,al ; set Send soh
clc ; success
ret
srsoh2: ret
; SET Send Double-char
srdbl PROC NEAR
mov min,0 ; lowest acceptable value
mov max,0ffh ; largest acceptable value
mov numhlp,offset dblhlp ; help
mov numerr,0 ; error message address
call num0 ; get numerical input
jc sreol3 ; c = error
cmp stflg,'R' ; setting Receive paramter?
je srdbl1 ; e = yes, no action
mov trans.sdbl,al ; store character to be doubled
mov dtrans.sdbl,al
clc
srdbl1: ret
srdbl ENDP
; SET Receive Ignore-char
srign PROC NEAR
mov min,0 ; lowest acceptable value
mov max,0ffh ; largest acceptable value
mov numhlp,offset dblhlp ; reuse help
mov numerr,0 ; error message address
call num0 ; get numerical input
jc srign1 ; c = error
cmp stflg,'S' ; setting SEND paramter?
je srign1 ; e = yes, no action
mov trans.rign,al ; store character to be ignored
mov dtrans.rign,al
clc
srign1: ret
srign ENDP
; SET SEND and RECEIVE TIMEOUT
srtim: mov min,0
mov max,94
mov numhlp,offset timhlp ; Reuse help message
mov numerr,0 ; error message
call num0 ; Common routine for parsing numerical input
jc srtim3 ; c = error
cmp stflg,'S' ; Setting SEND paramter?
je srtim1
mov trans.rtime,al
jmp short srtim2
srtim1: mov dtrans.stime,al
srtim2: mov ah,dtrans.stime
mov trans.stime,ah
clc
srtim3: ret
; SET SEND and RECEIVE PACKET LENGTH
; dtrans items are real, trans items are just for SHOW information
srpack: mov min,20
mov max,maxpack
mov numhlp,offset pakhlp ; help
mov numerr,offset pakerr ; error message
call num0
jnc srpaks0 ; nc = success
ret ; failure
srpaks0:cmp stflg,'S' ; setting send value?
jne srpakr ; ne = receive
mov dtrans.slong,ax ; set send max value
mov trans.slong,ax ; store current active length
mov dtrans.spsiz,dspsiz ; set regular 94 byte default
cmp ax,dspsiz ; longer than regular packet?
jae srpaks1 ; ae = yes
mov dtrans.spsiz,al ; shrink regular packet size too
mov trans.spsiz,al ; shrink regular packet size too
srpaks1:mov ax,maxpack ; maximum buffer size
xor dx,dx
mov cl,dtrans.windo ; current window slots
xor ch,ch
div cx ; get active send packet length
cmp ax,dtrans.slong ; longer than user specified?
jae srpaks4 ; ae = yes, employ user limit
mov cl,dtrans.spsiz ; regular packet length
xor ch,ch
cmp ax,cx ; windowed shorter than normal packet?
jae srpaks3 ; ae = no
mov trans.spsiz,al ; shrink regular pkt size
xor ah,ah
srpaks3:mov trans.slong,ax ; store current active length
srpaks4:clc ; success
ret
srpakr: mov dtrans.rlong,ax ; set receive max value
mov trans.rlong,ax ; store active length
mov dtrans.rpsiz,drpsiz ; set regular to default 94 bytes
mov trans.rpsiz,drpsiz
cmp ax,drpsiz ; longer than a regular packet?
jae srpakr1 ; ae = yes
mov dtrans.rpsiz,al ; shrink regular packet size too
mov trans.rpsiz,al
srpakr1:mov ax,maxpack ; maximum buffer size
xor dx,dx
mov cl,dtrans.windo ; current window slots
xor ch,ch
div cx ; get fully windowed packet length
cmp ax,dtrans.rlong ; longer than user specified?
jae srpakr4 ; ae = yes, employ user limit
mov cl,dtrans.rpsiz ; regular packet length
xor ch,ch
cmp ax,cx ; windowed shorter than normal packet?
jae srpakr3 ; ae = no
mov trans.rpsiz,al ; shrink regular packet length
xor ah,ah
srpakr3:mov trans.rlong,ax ; store active length
srpakr4:clc ; success
ret
; SET SEND and RECEIVE number of padding characters
srnpd: mov min,0
mov max,94
mov numhlp,offset timhlp ; reuse help message
mov numerr,0 ; error message
call num0 ; Parse numerical input
jc srnpd3 ; c = error
cmp stflg,'S' ; Setting SEND paramter?
je srnpd1 ; e = yes
mov trans.rpad,al ; set Receive padding
jmp short srnpd2
srnpd1: mov dtrans.spad,al ; set default Send padding
srnpd2: mov al,dtrans.spad
mov trans.spad,al ; update active array for I and S pkts
clc
srnpd3: ret
; SET SEND and RECEIVE padding character
srpad: mov min,0
mov max,127
mov numhlp,offset padhlp
mov numerr,offset padhlp
call num0 ; parse numerical input
jc srpad4 ; c = error
cmp ah,127 ; this is allowed
je srpad1
cmp ah,32
jb srpad1 ; between 0 and 31 is OK too
mov ah,prstr
mov dx,offset padhlp
int dos
srpad1: cmp stflg,'S' ; Send?
je srpad2 ; e = yes, else Receive
mov trans.rpadch,al ; store receive pad char
jmp short srpad3
srpad2: mov dtrans.spadch,al ; store Send pad char
srpad3: mov ah,dtrans.spadch
mov trans.spadch,ah ; update active array for I and S pkts
clc ; success
srpad4: ret
; SET SEND and RECEIVE control character prefix
srquo: mov min,33
mov max,126
mov numhlp,offset quohlp ; help message
mov numerr,0 ; error message
call num0 ; Parse numerical input
jc srquo3 ; c = error
cmp stflg,'S' ; Setting outgoing quote char?
je srquo1 ; e = yes
mov trans.rquote,al ; set Receive quote char
jmp short srquo2
srquo1: mov dtrans.squote,al ; set Send quote char
srquo2: clc
srquo3: ret
; SET SEND Pause number of milliseconds
srpaus: mov min,0
mov max,127
mov numhlp,offset pauhlp ; help
mov numerr,0
call num0 ; Parse numerical input
pushf ; save carry for error state
cmp stflg,'S' ; Setting SEND paramter?
je srpau0
popf
mov dx,offset ermes5 ; "Not implemented" msg
jmp reterr ; print error message
srpau0: popf
jc srpau1 ; c = error
mov spause,al ; store value
srpau1: ret
; SET TCP/IP address nnn.nnn.nnn.nnn
; SET TCP/IP subnetmask nnn.nnn.nnn.nnn
; SET TCP/IP gateway nnn.nnn.nnn.nnn
; SET TCP/IP primary-nameserver nnn.nnn.nnn.nnn
; SET TCP/IP secondary-nameserver nnn.nnn.nnn.nnn
; SET TCP/IP domain string
tcpipset proc near
mov ah,cmkey ; get keyword
mov dx,offset tcptable ; table
xor bx,bx ; help
call comnd
jnc tcpse1
ret
tcpse1: mov word ptr rdbuf,bx ; keyword index
cmp bx,1 ; local address help?
jne tcpse1a ; ne = no
mov bx,offset addrhelp ; address help
jmp short tcpse4
tcpse1a:cmp bx,2 ; domain name?
jne tcpse2 ; ne = no
mov bx,offset domainhlp ; domain help
jmp short tcpse4
tcpse2: cmp bx,6 ; subnet mask?
jne tcpse3 ; ne = no
mov bx,offset subnethlp
jmp short tcpse4
tcpse3: cmp bx,7 ; Host?
jne tcpse3a ; ne = no
mov bx,offset hosthlp
jmp short tcpse4
tcpse3a:mov bx,offset iphelp ; Internet number help
tcpse4: mov ah,cmword ; get a string
mov dx,offset rdbuf+2 ; work buffer
call comnd
jnc tcpse5
ret
tcpse5: push ax ; save string length in ax
mov ah,cmeol
call comnd
pop ax
jnc tcpse6
ret
tcpse6: mov si,offset rdbuf+2 ; user's string
mov bx,word ptr rdbuf ; comand kind
cmp bx,2 ; domain?
jne tcpse8 ; ne = no
mov di,offset tcpdomain
cmp ax,32 ; exceeded 32 chars?
jbe tcpse7 ; be = no
mov ah,prstr
mov dx,offset domainbad ; compain
int dos
stc
ret
tcpse7: cmp ax,32 ; address oversized?
jbe tcpse9 ; be = no
mov ah,prstr
mov dx,offset addressbad ; say bad address
int dos
stc
ret
tcpse8: mov di,offset tcpaddress
cmp bx,1 ; local address?
je tcpse9 ; e = yes
mov di,offset tcpsubnet
cmp bx,3 ; subnet?
je tcpse9 ; e = yes
mov di,offset tcpgateway
cmp bx,4 ; gateway?
je tcpse9
mov di,offset tcpprimens
cmp bx,5 ; primary-nameserver?
je tcpse9
mov di,offset tcpsecondns ; secondary-nameserer
cmp bx,6
je tcpse9
mov di,offset tcphost ; host name or number
cmp bx,7
je tcpse9
mov di,offset tcpbcast ; broadcast
tcpse9: call strcpy
clc
ret
tcpipset endp
; SET TRANSFER CHARACTER-SET {Latin1, Transparent}
sxfer proc near
mov dx,offset xfertab ; table of TRANSFER keywords
xor bx,bx
mov ah,cmkey ; get next keyword
call comnd
jc sxfer1 ; c = error
or bl,bl ; Character-set?
jnz sxfer1 ; nz = no
mov dx,offset xfchtab ; Character-set table
mov bx,offset xfchhlp ; help text
call keyend
jc sxfer1 ; c = error
mov dtrans.xchset,bl ; store transfer char set ident
mov trans.xchset,bl ; store transfer char set ident
cmp bl,2 ; Cyrillic?
jne sxfer1 ; ne = no
mov ax,flags.chrset ; get current file character set
mov flags.chrset,866 ; force CP866
cmp ax,866 ; was CP866/LATIN5 File Character set?
jne sxfer2 ; ne = no, show warning about force
clc
sxfer1: ret
sxfer2: mov dx,offset xfchbad ; show warning message
mov ah,prstr
int dos
clc
ret
sxfer endp
; SET TRANSLATION Connect mode translate characters
; SET TRANSLATION INPUT {Original-byte New-byte | ON | OFF}
; SET TRANSLATION KEYBOARD {ON | OFF}, default is ON
SETRX PROC NEAR ; translate incoming serial port char
mov ah,cmkey
mov dx,offset trnstab ; direction table (just one entry)
xor bx,bx ; no help
call comnd
jnc setrx0 ; nc = success
ret ; failure
setrx0: cmp bx,2 ; Keyboard?
jne setrx0b ; ne = no
jmp setr11 ; do keyboard
setrx0b:mov dx,offset rdbuf ; our work space
mov word ptr rdbuf,0 ; insert terminator
mov bx,offset srxhlp1 ; first help message
mov ah,cmword ; parse a word
call comnd ; get incoming byte pattern
jnc setrx0a ; nc = success
ret
setrx0a:or ax,ax ; any text given?
jz setr6 ; nz = no
mov temp,ax ; save byte count here
mov ax,word ptr rdbuf ; get first two characters
or ax,2020h ; convert upper to lower case
cmp ax,'fo' ; first part of word OFF?
je setr6 ; e = yes, go analyze
cmp ax,'no' ; word ON?
je setr6 ; e = yes, go do it
mov si,offset rdbuf ; convert text to number
call katoi ; number converter procedure, to ax
jnc setr1 ; nc = success
cmp temp,1 ; just one character given?
jne setr6 ; ne = no, so bad code
setr1: mov min,ax ; save byte code here
mov dx,offset rdbuf ; our work space
mov word ptr rdbuf,0 ; insert terminator
mov bx,offset srxhlp1 ; first help message
mov ah,cmword ; parse a word
call comnd ; get incoming byte pattern
jnc setr2 ; nc = success
ret ; failure
setr2: or ax,ax ; any text given?
jz setr6 ; z = no
mov temp,ax ; save byte count here
mov si,offset rdbuf ; convert text to number
call katoi ; number converter procedure
jnc setr3 ; nc = success
cmp temp,1 ; just one character given?
jne setr6 ; ne = no, so bad code or ON/OFF
setr3: mov max,ax ; save byte code here
mov ah,cmeol ; get a confirm
call comnd
jnc setr3a ; nc = success
ret ; failure
setr3a: mov bx,min ; bl = incoming byte code
xor bh,bh
mov ax,max ; al = local (translated) byte code
mov rxtable [bx],al ; store in rx translate table
clc ; success
ret
setr6: mov ah,cmeol ; get a confirm
call comnd
jnc setr6a ; nc = success
ret ; failure
setr6a: mov dx,offset badrx ; assume bad construction
or word ptr rdbuf,2020h ; convert to lower case
or rdbuf+2,20h ; first three chars
cmp word ptr rdbuf,'fo' ; key word OFF?
jne setr8 ; ne = no
cmp rdbuf+2,'f' ; last letter of OFF?
jne setr8 ; ne = no
mov rxtable+256,0 ; OFF is status byte = zero
mov dx,offset rxoffmsg ; say translation is turned off
jmp short setr9
setr8: cmp word ptr rdbuf,'no' ; keyword ON?
jne setr9a ; ne = no, error
mov rxtable+256,1 ; ON is status byte non-zero
mov dx,offset rxonmsg ; say translation is turned on
setr9: cmp taklev,0 ; executing from a Take file?
je setr9a ; e = no
cmp flags.takflg,0 ; echo contents of Take file?
je setr10 ; e = no
setr9a: mov ah,prstr ; bad number message
int dos
setr10: clc
ret
setr11: mov ah,cmkey ; SET TRANSLATION KEYBOARD
mov dx,offset ontab ; on/off
xor bx,bx
call comnd
jnc setr12 ; nc = success
ret
setr12: mov ah,cmeol ; get a confirm
call comnd
jnc setr13 ; nc = success
ret ; failure
setr13: mov flags.xltkbd,bl ; set keyboard translation on/off
clc
ret
SETRX ENDP
; SET TRANSMIT {FILL, LF, Prompt} {ON, OFF, or value}
SETXMIT proc near
mov dx,offset xmitab ; TRANSMIT keyword table
xor bx,bx
mov ah,cmkey ; get keyword
call comnd
jnc setxmi1 ; nc = success
ret
setxmi1:cmp bl,2 ; SET TRANSMIT PROMPT?
jne setxmi2 ; ne = no
mov ah,cmword
mov dx,offset rdbuf+1 ; put answer here
mov bx,offset xpmthlp
call comnd
jc setxmi1d ; c = error
push ax ; save length
mov ah,cmeol ; get a confirm
call comnd
pop cx ; recover length to cx
jc setxmi1d ; c = failure
mov al,rdbuf+1
cmp cx,1 ; a single char?
je setxmi1c ; e = yes, use it as the prompt char
mov si,offset rdbuf+1
cmp byte ptr [si],'\' ; already quoted?
je setxmi1b ; e = yes
mov rdbuf,'\' ; add a numerical quote
dec si ; point to our escape char
setxmi1b:call katoi ; convert number in rdbuf
jc setxmi1d ; c = no number, error
setxmi1c:mov script.xmitpmt,al ; store new prompt value
setxmi1d:ret
setxmi2:cmp bl,1 ; LF?
jne setxmi3 ; ne = no
mov dx,offset ontab ; on or off table
xor bx,bx
call keyend
jc setxmix ; c = failure
mov script.xmitlf,bl ; set the xmitlf flag
ret
setxmi3:mov ah,cmword ; FILL, get a word sized token
mov dx,offset rdbuf+1 ; put it here
mov bx,offset xfilhlp ; help
call comnd
jc setxmix ; c = failure
push ax ; save length in ah
mov ah,cmeol ; get a confirm
call comnd
pop ax
jc setxmix ; c = failure
cmp ax,1 ; just one character?
ja setxmi4 ; a = no, there's more
mov al,rdbuf+1 ; get the char
mov script.xmitfill,al ; store Fill char
ret
setxmi4:mov ax,word ptr rdbuf+1
or ax,2020h ; to lower
cmp ax,'on' ; "none"?
jne setxmi5 ; ne = no
mov script.xmitfill,0 ; no Filling
ret
setxmi5:cmp ax,'ps' ; "space"?
jne setxmi6 ; ne = no
mov script.xmitfill,' ' ; use space as filler
ret
setxmi6:mov si,offset rdbuf+1
cmp byte ptr [si],'\' ; already quoted?
je setxmi7 ; e = yes
mov rdbuf,'\' ; add a numerical quote
dec si ; point to our escape char
setxmi7:call katoi ; convert number in rdbuf
jc setxmix ; c = no number, error
mov script.xmitfill,al ; set the xmitfill flag
setxmix:ret
SETXMIT endp
; SET UNKNOWN-CHARACTER-SET {DISCARD, KEEP}, default is KEEP
unkchset proc near
mov dx,offset unkctab ; keep/reject keyword table
mov bx,offset unkchhlp
call keyend
jc unkchx ; c = failure
mov flags.unkchs,bl ; 0 = keep, else reject
unkchx: ret
unkchset endp
; Common routine for parsing numerical input
; Enter with numhlp = offset of help message, numerr = offset of optional
; error message, min, max = allowable range of values.
; Returns value in ax, or does parse error return.
; Changes ax,bx,dx,si. [jrd] 18 Oct 1987
num0: mov dx,offset rdbuf+1 ; were to put text
mov word ptr rdbuf,0 ; clear the buffer
mov bx,numhlp ; help text
mov ah,cmword ; get a word
call comnd
jc num0x ; c = failure
mov ah,cmeol
call comnd ; Get a confirm
jc num0x ; c = failure
; second entry point
numwd: mov si,offset rdbuf+1
cmp rdbuf+1,'\' ; already quoted?
je num0a ; e = yes
mov rdbuf,'\' ; add a numerical quote
dec si ; point to our escape char
num0a: call katoi ; convert number in rdbuf
jc num0er ; c = no number, error
cmp ax,max ; largest permitted value
ja num0er ; a = error
cmp ax,min ; smallest permitted value
jb num0er ; b = error
clc
num0x: ret ; return value in ax
num0er: mov ah,prstr
mov dx,numerr ; comand-specific error message, if any
or dx,dx ; was any given?
jz num0e1 ; z = no, use generic msg
int dos ; show given error message
jmp short num0e2
num0e1: mov dx,offset nummsg1 ; get address of numeric error message
int dos
mov ax,min ; smallest permitted number
call decout ; display decimal number in ax
mov ah,prstr
mov dx,offset nummsg2 ; "and"
int dos
mov ax,max ; largest permitted number
call decout
mov ah,prstr
mov dx,offset crlf
int dos
num0e2: stc
ret
; routine to print an error message, then exit without error status
; expects message in dx
reterr proc near
mov ah,prstr
int dos
clc
ret
reterr endp
code ends
end